5 #include "cmdhflegic.h" 
  12 static int CmdHelp(const char *Cmd
); 
  14 int CmdLegicRFRead(const char *Cmd
) 
  16   int byte_count
=0,offset
=0; 
  17   sscanf(Cmd
, "%i %i", &offset
, &byte_count
); 
  18   if(byte_count 
== 0) byte_count 
= 256; 
  19   if(byte_count 
+ offset 
> 256) byte_count 
= 256 - offset
; 
  20   UsbCommand c
={CMD_READER_LEGIC_RF
, {offset
, byte_count
, 0}}; 
  25 static command_t CommandTable
[] =  
  27   {"help",        CmdHelp
,        1, "This help"}, 
  28   {"reader",      CmdLegicRFRead
, 0, "[offset [length]] -- read bytes from a LEGIC card"}, 
  29   {"decode",      CmdLegicDecode
, 0, "Display deobfuscated and decoded LEGIC RF tag data (use after hf legic reader)"}, 
  33 int CmdHFLegic(const char *Cmd
) 
  35   CmdsParse(CommandTable
, Cmd
); 
  39 int CmdHelp(const char *Cmd
) 
  41   CmdsHelp(CommandTable
); 
  46  *  Output BigBuf and deobfuscate LEGIC RF tag data. 
  47  *   This is based on information given in the talk held 
  48  *  by Henryk Ploetz and Karsten Nohl at 26c3 
  49  *  FIXME: will crash if sample buffer does not contain valid legic data 
  51 int CmdLegicDecode(const char *Cmd
) 
  60   int data_buf
[1032]; // receiver buffer 
  61   char out_string
[3076]; // just use big buffer - bad practice 
  67   // copy data from proxmark into buffer 
  68   for (i 
= 0; i 
< 256; i 
+= 12, h 
+= 48) { 
  69     UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {i
, 0, 0}}; 
  71     WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
); 
  73     for (j 
= 0; j 
< 48; j 
+= 8) { 
  74       for (k 
= 0; k 
< 8; k
++) { 
  75         data_buf
[h
+j
+k
] = sample_buf
[j
+k
]; 
  78       if (delivered 
>= 1024) 
  83   // Output CDF System area (9 bytes) plus remaining header area (12 bytes) 
  85   PrintAndLog("\nCDF: System Area"); 
  87   PrintAndLog("MCD: %02x, MSN: %02x %02x %02x, MCC: %02x", 
  97   switch (data_buf
[5]&0x7f) { 
  99       strncpy(token_type
, "IAM",sizeof(token_type
)); 
 102       strcpy(token_type
, "SAM"); 
 105       strcpy(token_type
, "GAM"); 
 108       strcpy(token_type
, "???"); 
 112   stamp_len 
= 0xfc - data_buf
[6]; 
 114   PrintAndLog("DCF: %02x %02x, Token_Type=%s (OLE=%01u), Stamp_len=%02u", 
 118     (data_buf
[5]&0x80)>>7, 
 122   PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, raw=%02x, SSC=%02x", 
 124     (data_buf
[7]&0x70)>>4, 
 125     (data_buf
[7]&0x80)>>7, 
 130   PrintAndLog("Remaining Header Area"); 
 132   PrintAndLog("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 
 148   PrintAndLog("\nADF: User Area"); 
 151   for (n
=0; n
<64; n
++) { 
 152     segment_len 
= ((data_buf
[i
+1]^crc
)&0x0f) * 256 + (data_buf
[i
]^crc
); 
 153     segment_flag 
= ((data_buf
[i
+1]^crc
)&0xf0)>>4; 
 155     wrp 
= (data_buf
[i
+2]^crc
); 
 156     wrc 
= ((data_buf
[i
+3]^crc
)&0x70)>>4; 
 158      PrintAndLog("Segment %02u: raw header=%02x %02x %02x %02x, flag=%01x (valid=%01u, last=%01u), len=%04u, WRP=%02u, WRC=%02u, RD=%01u, CRC=%02x", 
 165       (segment_flag
&0x4)>>2, 
 166       (segment_flag
&0x8)>>3, 
 170       ((data_buf
[i
+3]^crc
)&0x80)>>7, 
 177       PrintAndLog("WRC protected area:"); 
 178       for (k
=0, j
=0; k 
< wrc
; k
++, i
++, j 
+= 3) { 
 179         sprintf(&out_string
[j
], "%02x", (data_buf
[i
]^crc
)); 
 180         out_string
[j
+2] = ' '; 
 183       out_string
[j
] = '\0'; 
 185       PrintAndLog("%s", out_string
); 
 189       PrintAndLog("Remaining write protected area:"); 
 191       for (k
=0, j
=0; k 
< (wrp
-wrc
); k
++, i
++, j 
+= 3) { 
 192         sprintf(&out_string
[j
], "%02x", (data_buf
[i
]^crc
)); 
 193         out_string
[j
+2] = ' '; 
 196       out_string
[j
] = '\0'; 
 198       PrintAndLog("%s", out_string
); 
 200         sprintf(out_string
,"Card ID: %2X%02X%02X",data_buf
[i
-4]^crc
,data_buf
[i
-3]^crc
,data_buf
[i
-2]^crc
); 
 201         PrintAndLog("%s", out_string
); 
 205     PrintAndLog("Remaining segment payload:"); 
 206     for (k
=0, j
=0; k 
< (segment_len 
- wrp 
- 5); k
++, i
++, j 
+= 3) { 
 207       sprintf(&out_string
[j
], "%02x", (data_buf
[i
]^crc
)); 
 208       out_string
[j
+2] = ' '; 
 211     out_string
[j
] = '\0'; 
 213     PrintAndLog("%s", out_string
); 
 215     // end with last segment 
 216     if (segment_flag 
& 0x8)