Proxmark developers community

Research, development and trades concerning the powerful Proxmark3 device!

You are not logged in.

#1 2010-01-05 12:57:39

sz
Member
Registered: 2010-01-05
Posts: 1

Patch for deobfuscation of legic rf reader output

I have attached a patch to command.c that retrieves the read legic rf data and displays it in a deobfuscated manner.
Code is quite ugly, please feel free to improve... (license: GPL v2).

---

Index: client/command.c
===================================================================
--- client/command.c  (Revision 303)
+++ client/command.c  (Arbeitskopie)
@@ -2792,6 +2792,177 @@
   SendCommand(&c);

 }

 

+/*

+ *  Output BigBuf and deobfuscate LEGIC RF tag data.

+ *   This is based on information given in the talk held

+ *  by Henryk Ploetz and Karsten Nohl at 26c3

+ *  FIXME: will crash if sample buffer does not contain valid legic data

+ */

+static void CmdLegicDecode()

+{

+  int h, i, j, k, n;

+  int segment_len = 0;

+  int segment_flag = 0;

+  int stamp_len = 0;

+  int crc = 0;

+  int wrp = 0;

+  int wrc = 0;

+  int data_buf[1032]; // receiver buffer

+  char out_string[3076]; // just use big buffer - bad practice

+  char token_type[4];

+  int delivered = 0;

+

+  h = 0;

+  

+  // copy data from proxmark into buffer

+  for (i = 0; i < 256; i += 12, h += 48) {

+    UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}};

+    SendCommand(&c);

+    wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K);

+    

+    for (j = 0; j < 48; j += 8) {

+      for (k = 0; k < 8; k++) {

+        data_buf[h+j+k] = sample_buf[j+k];

+      }

+      delivered += 8;

+      if (delivered >= 1024)

+        break;

+    }

+  }

+    

+  // Output CDF System area (9 bytes) plus remaining header area (12 bytes)

+  

+  PrintToScrollback("\nCDF: System Area");

+  

+  PrintToScrollback("MCD: %02x, MSN: %02x %02x %02x, MCC: %02x",

+    data_buf[0],

+    data_buf[1],

+    data_buf[2],

+    data_buf[3],

+    data_buf[4]

+  );

+  

+  crc = data_buf[4];

+  

+  switch (data_buf[5]&0x7f) {

+    case 0x00 ... 0x2f:

+      strcpy(token_type, "IAM");

+      break;

+    case 0x30 ... 0x6f:

+      strcpy(token_type, "SAM");

+      break;

+    case 0x70 ... 0x7f:

+      strcpy(token_type, "GAM");

+      break;

+    default:

+      strcpy(token_type, "???");

+      break;

+  }

+  

+  stamp_len = 0xfc - data_buf[6];

+  

+  PrintToScrollback("DCF: %02x %02x, Token_Type=%s (OLE=%01u), Stamp_len=%02u",

+    data_buf[5],

+    data_buf[6],

+    token_type,

+    (data_buf[5]&0x80)>>7,

+    stamp_len

+  );

+  

+  PrintToScrollback("WRP=%02u, WRC=%01u, RD=%01u, raw=%02x, SSC=%02x",

+    data_buf[7]&0x0f,

+    (data_buf[7]&0x70)>>4,

+    (data_buf[7]&0x80)>>7,

+    data_buf[7],

+    data_buf[8]

+  );

+  

+  PrintToScrollback("Remaining Header Area");

+  

+  PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",

+      data_buf[9],

+    data_buf[10],

+    data_buf[11],

+    data_buf[12],

+    data_buf[13],

+    data_buf[14],

+    data_buf[15],

+    data_buf[16],

+    data_buf[17],

+    data_buf[18],

+    data_buf[19],

+    data_buf[20],

+    data_buf[21]

+  );

+  

+  PrintToScrollback("\nADF: User Area");

+  

+    i = 22;  

+  for (n=0; n<64; n++) {

+    segment_len = ((data_buf[i+1]^crc)&0x0f) * 256 + (data_buf[i]^crc);

+    segment_flag = ((data_buf[i+1]^crc)&0xf0)>>4;

+    

+    wrp = (data_buf[i+2]^crc);

+    wrc = ((data_buf[i+3]^crc)&0x70)>>4;

+    

+     PrintToScrollback("Segment %02u: raw header=%02x %02x %02x %02x, flag=%01x (valid=%01u, last=%01u), len=%04u, WRP=%02u, WRC=%02u, RD=%01u, CRC=%02x",

+      n,

+      data_buf[i]^crc,

+      data_buf[i+1]^crc,

+      data_buf[i+2]^crc,

+      data_buf[i+3]^crc,

+      segment_flag,

+      (segment_flag&0x4)>>2,

+      (segment_flag&0x8)>>3,

+      segment_len,

+      wrp,

+      wrc,

+      ((data_buf[i+3]^crc)&0x80)>>7,

+      (data_buf[i+4]^crc)

+    );

+    

+    i+=5;

+    

+    // Output WRC protected area

+    if (wrc>0) {

+      for (k=0, j=0; k < wrc; k++, i++, j += 3) {

+        sprintf(&out_string[j], "%02x", (data_buf[i]^crc));

+        out_string[j+2] = ' ';

+      };

+        

+      out_string[j] = '\0';

+    

+      PrintToScrollback("%s", out_string);

+    }

+    

+    // Output remaining write protected area

+    if (wrp>wrc) {

+      for (k=0, j=0; k < (wrp-wrc); k++, i++, j += 3) {

+        sprintf(&out_string[j], "%02x", (data_buf[i]^crc));

+        out_string[j+2] = ' ';

+      };

+    

+      out_string[j] = '\0';

+    

+      PrintToScrollback("%s", out_string);

+    }

+    

+    // Output remaining segment payload

+    for (k=0, j=0; k < (segment_len - wrp - 5); k++, i++, j += 3) {

+      sprintf(&out_string[j], "%02x", (data_buf[i]^crc));

+      out_string[j+2] = ' ';

+    };

+    

+    out_string[j] = '\0';

+    

+    PrintToScrollback("%s", out_string);

+    

+    // end with last segment

+    if (segment_flag & 0x8)

+      return;

+  };

+}

+

 typedef void HandlerFunction(char *cmdline);

 

 /* in alphabetic order */

@@ -2848,6 +3019,7 @@
   {"lcd",      CmdLcd,      0, "<HEX command> <count> -- Send command/data to LCD"},

   {"lcdreset",    CmdLcdReset,    0, "Hardware reset LCD"},

   {"legicrfread",    CmdLegicRfRead,    0, "Start the LEGIC RF reader"},

+  {"legicdecode", CmdLegicDecode,  0, "Display deobfuscated and decoded LEGIC RF tag data (use after legicrfread)"},

   {"load",    CmdLoad,    1, "<filename> -- Load trace (to graph window"},

   {"locomread",    CmdLoCommandRead,  0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},

   {"loread",    CmdLoread,    0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},

Offline

#2 2010-01-08 16:14:26

cavac
Member
Registered: 2010-01-03
Posts: 2

Re: Patch for deobfuscation of legic rf reader output

Cool thanks

Offline

Board footer

Powered by FluxBB