]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlfem4x.c
   1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // Low frequency EM4x commands 
   9 //----------------------------------------------------------------------------- 
  14 //#include "proxusb.h" 
  15 #include "proxmark3.h" 
  18 #include "cmdparser.h" 
  21 #include "cmdlfem4x.h" 
  23 static int CmdHelp(const char *Cmd
); 
  25 /* Read the ID of an EM410x tag. 
  27  *   1111 1111 1           <-- standard non-repeatable header 
  28  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
  30  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
  31  *   0                     <-- stop bit, end of tag 
  33 int CmdEM410xRead(const char *Cmd
) 
  35   int i
, j
, clock
, header
, rows
, bit
, hithigh
, hitlow
, first
, bit2idx
, high
, low
; 
  39   uint8_t BitStream
[MAX_GRAPH_TRACE_LEN
]; 
  42   /* Detect high and lows and clock */ 
  43   for (i 
= 0; i 
< GraphTraceLen
; i
++) 
  45     if (GraphBuffer
[i
] > high
) 
  46       high 
= GraphBuffer
[i
]; 
  47     else if (GraphBuffer
[i
] < low
) 
  52   clock 
= GetClock(Cmd
, high
, 0); 
  54   /* parity for our 4 columns */ 
  55   parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
  58   /* manchester demodulate */ 
  60   for (i 
= 0; i 
< (int)(GraphTraceLen 
/ clock
); i
++) 
  66     /* Find out if we hit both high and low peaks */ 
  67     for (j 
= 0; j 
< clock
; j
++) 
  69       if (GraphBuffer
[(i 
* clock
) + j
] == high
) 
  71       else if (GraphBuffer
[(i 
* clock
) + j
] == low
) 
  74       /* it doesn't count if it's the first part of our read 
  75        because it's really just trailing from the last sequence */ 
  76       if (first 
&& (hithigh 
|| hitlow
)) 
  81       if (hithigh 
&& hitlow
) 
  85     /* If we didn't hit both high and low peaks, we had a bit transition */ 
  86     if (!hithigh 
|| !hitlow
) 
  89     BitStream
[bit2idx
++] = bit
; 
  93   /* We go till 5 before the graph ends because we'll get that far below */ 
  94   for (i 
= 1; i 
< bit2idx 
- 5; i
++) 
  96     /* Step 2: We have our header but need our tag ID */ 
  97     if (header 
== 9 && rows 
< 10) 
  99       /* Confirm parity is correct */ 
 100       if ((BitStream
[i
] ^ BitStream
[i
+1] ^ BitStream
[i
+2] ^ BitStream
[i
+3]) == BitStream
[i
+4]) 
 102         /* Read another byte! */ 
 103         sprintf(id
+rows
, "%x", (8 * BitStream
[i
]) + (4 * BitStream
[i
+1]) + (2 * BitStream
[i
+2]) + (1 * BitStream
[i
+3])); 
 106         /* Keep parity info */ 
 107         parity
[0] ^= BitStream
[i
]; 
 108         parity
[1] ^= BitStream
[i
+1]; 
 109         parity
[2] ^= BitStream
[i
+2]; 
 110         parity
[3] ^= BitStream
[i
+3]; 
 112         /* Move 4 bits ahead */ 
 116       /* Damn, something wrong! reset */ 
 119         PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows 
+ 1, i
); 
 121         /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ 
 122         i 
-= 9 + (5 * rows
) - 5; 
 128     /* Step 3: Got our 40 bits! confirm column parity */ 
 131       /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ 
 132       if (BitStream
[i
] == parity
[0] && BitStream
[i
+1] == parity
[1] && 
 133         BitStream
[i
+2] == parity
[2] && BitStream
[i
+3] == parity
[3] && 
 137         PrintAndLog("EM410x Tag ID: %s", id
); 
 143       /* Crap! Incorrect parity or no stop bit, start all over */ 
 148         /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ 
 153     /* Step 1: get our header */ 
 156       /* Need 9 consecutive 1's */ 
 157       if (BitStream
[i
] == 1) 
 160       /* We don't have a header, not enough consecutive 1 bits */ 
 166   /* if we've already retested after flipping bits, return */ 
 170   /* if this didn't work, try flipping bits */ 
 171   for (i 
= 0; i 
< bit2idx
; i
++) 
 177 /* emulate an EM410X tag 
 179  *   1111 1111 1           <-- standard non-repeatable header 
 180  *   XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID 
 182  *   CCCC                  <-- each bit here is parity for the 10 bits above in corresponding column 
 183  *   0                     <-- stop bit, end of tag 
 185 int CmdEM410xSim(const char *Cmd
) 
 187   int i
, n
, j
, h
, binary
[4], parity
[4]; 
 189   /* clock is 64 in EM410x tags */ 
 192   /* clear our graph */ 
 195   /* write it out a few times */ 
 196   for (h 
= 0; h 
< 4; h
++) 
 198     /* write 9 start bits */ 
 199     for (i 
= 0; i 
< 9; i
++) 
 200       AppendGraph(0, clock
, 1); 
 202     /* for each hex char */ 
 203     parity
[0] = parity
[1] = parity
[2] = parity
[3] = 0; 
 204     for (i 
= 0; i 
< 10; i
++) 
 206       /* read each hex char */ 
 207       sscanf(&Cmd
[i
], "%1x", &n
); 
 208       for (j 
= 3; j 
>= 0; j
--, n
/= 2) 
 211       /* append each bit */ 
 212       AppendGraph(0, clock
, binary
[0]); 
 213       AppendGraph(0, clock
, binary
[1]); 
 214       AppendGraph(0, clock
, binary
[2]); 
 215       AppendGraph(0, clock
, binary
[3]); 
 217       /* append parity bit */ 
 218       AppendGraph(0, clock
, binary
[0] ^ binary
[1] ^ binary
[2] ^ binary
[3]); 
 220       /* keep track of column parity */ 
 221       parity
[0] ^= binary
[0]; 
 222       parity
[1] ^= binary
[1]; 
 223       parity
[2] ^= binary
[2]; 
 224       parity
[3] ^= binary
[3]; 
 228     AppendGraph(0, clock
, parity
[0]); 
 229     AppendGraph(0, clock
, parity
[1]); 
 230     AppendGraph(0, clock
, parity
[2]); 
 231     AppendGraph(0, clock
, parity
[3]); 
 234     AppendGraph(0, clock
, 0); 
 237   /* modulate that biatch */ 
 238   CmdManchesterMod(""); 
 241   RepaintGraphWindow(); 
 247 /* Function is equivalent of loread + losamples + em410xread 
 248  * looped until an EM410x tag is detected */ 
 249 int CmdEM410xWatch(const char *Cmd
) 
 255   } while ( ! CmdEM410xRead("")); 
 259 /* Read the transmitted data of an EM4x50 tag 
 262  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 263  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 264  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 265  *  XXXXXXXX [row parity bit (even)] <- 8 bits plus parity 
 266  *  CCCCCCCC                         <- column parity bits 
 268  *  LW                               <- Listen Window 
 270  * This pattern repeats for every block of data being transmitted. 
 271  * Transmission starts with two Listen Windows (LW - a modulated 
 272  * pattern of 320 cycles each (32/32/128/64/64)). 
 274  * Note that this data may or may not be the UID. It is whatever data 
 275  * is stored in the blocks defined in the control word First and Last 
 276  * Word Read values. UID is stored in block 32. 
 278 int CmdEM4x50Read(const char *Cmd
) 
 280   int i
, j
, startblock
, skip
, block
, start
, end
, low
, high
; 
 281   bool complete
= false; 
 282   int tmpbuff
[MAX_GRAPH_TRACE_LEN 
/ 64]; 
 286   memset(tmpbuff
, 0, MAX_GRAPH_TRACE_LEN 
/ 64); 
 288   /* first get high and low values */ 
 289   for (i 
= 0; i 
< GraphTraceLen
; i
++) 
 291     if (GraphBuffer
[i
] > high
) 
 292       high 
= GraphBuffer
[i
]; 
 293     else if (GraphBuffer
[i
] < low
) 
 294       low 
= GraphBuffer
[i
]; 
 297   /* populate a buffer with pulse lengths */ 
 300   while (i 
< GraphTraceLen
) 
 302     // measure from low to low 
 303     while ((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 306     while ((GraphBuffer
[i
] < high
) && (i
<GraphTraceLen
)) 
 308     while ((GraphBuffer
[i
] > low
) && (i
<GraphTraceLen
)) 
 310     if (j
>(MAX_GRAPH_TRACE_LEN
/64)) { 
 313     tmpbuff
[j
++]= i 
- start
; 
 316   /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ 
 319   for (i
= 0; i 
< j 
- 4 ; ++i
) 
 322     if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 323       if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 324         if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 325           if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 333   /* skip over the remainder of the LW */ 
 334   skip 
+= tmpbuff
[i
+1]+tmpbuff
[i
+2]; 
 335   while (skip 
< MAX_GRAPH_TRACE_LEN 
&& GraphBuffer
[skip
] > low
) 
 339   /* now do it again to find the end */ 
 341   for (i 
+= 3; i 
< j 
- 4 ; ++i
) 
 344     if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 345       if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 346         if (tmpbuff
[i
+2] >= 190 && tmpbuff
[i
+2] <= 194) 
 347           if (tmpbuff
[i
+3] >= 126 && tmpbuff
[i
+3] <= 130) 
 355     PrintAndLog("Found data at sample: %i",skip
); 
 358     PrintAndLog("No data found!"); 
 359     PrintAndLog("Try again with more samples."); 
 365     PrintAndLog("*** Warning!"); 
 366     PrintAndLog("Partial data - no end found!"); 
 367     PrintAndLog("Try again with more samples."); 
 370   /* get rid of leading crap */ 
 371   sprintf(tmp
,"%i",skip
); 
 374   /* now work through remaining buffer printing out data blocks */ 
 379     PrintAndLog("Block %i:", block
); 
 380     // mandemod routine needs to be split so we can call it for data 
 381     // just print for now for debugging 
 382     CmdManchesterDemod("i 64"); 
 384     /* look for LW before start of next block */ 
 385     for ( ; i 
< j 
- 4 ; ++i
) 
 388       if (tmpbuff
[i
] >= 190 && tmpbuff
[i
] <= 194) 
 389         if (tmpbuff
[i
+1] >= 126 && tmpbuff
[i
+1] <= 130) 
 392     while (GraphBuffer
[skip
] > low
) 
 395     sprintf(tmp
,"%i",skip
); 
 403 int CmdEM410xWrite(const char *Cmd
) 
 408   sscanf(Cmd
, "%" PRIx64 
" %d", &id
, &card
); 
 410   if (id 
>= 0x10000000000) { 
 411     PrintAndLog("Error! Given EM410x ID is longer than 40 bits.\n"); 
 416     PrintAndLog("Error! Bad card type selected.\n"); 
 420   PrintAndLog("Writing %s tag with UID 0x%010" PRIx64
, card 
? "T55x7":"T5555", id
); 
 421   UsbCommand c 
= {CMD_EM410X_WRITE_TAG
, {card
, (uint32_t)(id 
>> 32), (uint32_t)id
}}; 
 427 int CmdReadWord(const char *Cmd
) 
 429   int Word 
= 16; //default to invalid word 
 432   sscanf(Cmd
, "%d", &Word
); 
 435     PrintAndLog("Word must be between 0 and 15"); 
 439   PrintAndLog("Reading word %d", Word
); 
 441   c
.cmd 
= CMD_EM4X_READ_WORD
; 
 442   c
.d
.asBytes
[0] = 0x0; //Normal mode 
 450 int CmdReadWordPWD(const char *Cmd
) 
 452   int Word 
= 16; //default to invalid word 
 453   int Password 
= 0xFFFFFFFF; //default to blank password 
 456   sscanf(Cmd
, "%d %x", &Word
, &Password
); 
 459     PrintAndLog("Word must be between 0 and 15"); 
 463   PrintAndLog("Reading word %d with password %08X", Word
, Password
); 
 465   c
.cmd 
= CMD_EM4X_READ_WORD
; 
 466   c
.d
.asBytes
[0] = 0x1; //Password mode 
 474 int CmdWriteWord(const char *Cmd
) 
 476   int Word 
= 16; //default to invalid block 
 477   int Data 
= 0xFFFFFFFF; //default to blank data 
 480   sscanf(Cmd
, "%x %d", &Data
, &Word
); 
 483     PrintAndLog("Word must be between 0 and 15"); 
 487   PrintAndLog("Writting word %d with data %08X", Word
, Data
); 
 489   c
.cmd 
= CMD_EM4X_WRITE_WORD
; 
 490   c
.d
.asBytes
[0] = 0x0; //Normal mode 
 498 int CmdWriteWordPWD(const char *Cmd
) 
 500   int Word 
= 8; //default to invalid word 
 501   int Data 
= 0xFFFFFFFF; //default to blank data 
 502   int Password 
= 0xFFFFFFFF; //default to blank password 
 505   sscanf(Cmd
, "%x %d %x", &Data
, &Word
, &Password
); 
 508     PrintAndLog("Word must be between 0 and 15"); 
 512   PrintAndLog("Writting word %d with data %08X and password %08X", Word
, Data
, Password
); 
 514   c
.cmd 
= CMD_EM4X_WRITE_WORD
; 
 515   c
.d
.asBytes
[0] = 0x1; //Password mode 
 525 static command_t CommandTable
[] = 
 527   {"help", CmdHelp
, 1, "This help"}, 
 528   {"em410xread", CmdEM410xRead
, 1, "[clock rate] -- Extract ID from EM410x tag"}, 
 529   {"em410xsim", CmdEM410xSim
, 0, "<UID> -- Simulate EM410x tag"}, 
 530   {"em410xwatch", CmdEM410xWatch
, 0, "Watches for EM410x tags"}, 
 531   {"em410xwrite", CmdEM410xWrite
, 1, "<UID> <'0' T5555> <'1' T55x7> -- Write EM410x UID to T5555(Q5) or T55x7 tag"}, 
 532   {"em4x50read", CmdEM4x50Read
, 1, "Extract data from EM4x50 tag"}, 
 533   {"readword", CmdReadWord
, 1, "<Word> -- Read EM4xxx word data"}, 
 534   {"readwordPWD", CmdReadWordPWD
, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"}, 
 535   {"writeword", CmdWriteWord
, 1, "<Data> <Word> -- Write EM4xxx word data"}, 
 536   {"writewordPWD", CmdWriteWordPWD
, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"}, 
 537   {NULL
, NULL
, 0, NULL
} 
 540 int CmdLFEM4X(const char *Cmd
) 
 542   CmdsParse(CommandTable
, Cmd
); 
 546 int CmdHelp(const char *Cmd
) 
 548   CmdsHelp(CommandTable
);