├── README └── iclass_eeprom_dump-d2xx.c /README: -------------------------------------------------------------------------------- 1 | iClass Reader Tools 2 | by brad.antoniewicz@foundstone.com 3 | ------------------------------------------------- 4 | 5 | iClass EEPROM Dumper (iclass_eeprom_dump) 6 | Using method described here: 7 | http://proxclone.com/pdfs/iClass_Key_Extraction.pdf 8 | 9 | A lot of code was borrowed from here: 10 | http://www.openpcd.org/git-view/iclass-security/tree/pic18-icsp/uMain.cpp 11 | 12 | According to 13 | http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf 14 | 15 | The FTDI TTL-232R-5V-WE pin out is: 16 | 17 | 1 - Black 18 | 2 - Brown 19 | 3 - Red 20 | 4 - Orange 21 | 5 - Yellow 22 | 6 - Green 23 | 24 | According to 25 | http://www.openpcd.org/images/HID-iCLASS-security.pdf 26 | 27 | The HID RW300/RW400 ICSP pin out is (on the back under the tape, 28 | starting from left to right, with the sticker on the bottom): 29 | 30 | 1 - VSS 31 | 2 - VDD 32 | 3 - VPP/MCLR 33 | 4 - PGD 34 | 5 - PGC 35 | 6 - PGM 36 | 37 | So our pin out will be: 38 | 39 | FTDI COLOR -> HID PIN -> HID ICSP 40 | Black -> 1 -> VSS 41 | Red -> 2 -> VDD 42 | N/A -> 3 -> VPP 43 | Green -> 4 -> PGD 44 | Orange -> 5 -> PGC 45 | Brown -> 6 -> PGM 46 | 47 | For VPP we'll use an external 9V battery, just connect 48 | the VCC (+) on the battery to the VPP location when prompted 49 | (helps to have a switch) and the GND (-) to VSS 50 | 51 | This uses the FTDI-D2XX drivers. Get them from 52 | http://www.ftdichip.com/Drivers/D2XX.htm 53 | and follow the readme 54 | 55 | -------------------------------------------------------------------------------- /iclass_eeprom_dump-d2xx.c: -------------------------------------------------------------------------------- 1 | // build with gcc -lftd2xx -o iclass_eeprom_dump-d2xx iclass_eeprom_dump-d2xx.c 2 | 3 | /* 4 | 5 | iClass EEPROM Dumper 6 | by brad.antoniewicz@foundstone.com 7 | ------------------------------------------------- 8 | 9 | Using method described here: 10 | http://proxclone.com/pdfs/iClass_Key_Extraction.pdf 11 | 12 | A lot of code was borrowed from here: 13 | http://www.openpcd.org/git-view/iclass-security/tree/pic18-icsp/uMain.cpp 14 | 15 | According to 16 | http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf 17 | 18 | The FTDI TTL-232R-5V-WE pin out is: 19 | 20 | 1 - Black 21 | 2 - Brown 22 | 3 - Red 23 | 4 - Orange 24 | 5 - Yellow 25 | 6 - Green 26 | 27 | According to 28 | http://www.openpcd.org/images/HID-iCLASS-security.pdf 29 | 30 | The HID RW300/RW400 ICSP pin out is (on the back under the tape, 31 | starting from left to right, with the sticker on the bottom): 32 | 33 | 1 - VSS 34 | 2 - VDD 35 | 3 - VPP/MCLR 36 | 4 - PGD 37 | 5 - PGC 38 | 6 - PGM 39 | 40 | So our pin out will be: 41 | 42 | FTDI COLOR -> HID PIN -> HID ICSP 43 | Black -> 1 -> VSS 44 | Red -> 2 -> VDD 45 | N/A -> 3 -> VPP 46 | Green -> 4 -> PGD 47 | Orange -> 5 -> PGC 48 | Brown -> 6 -> PGM 49 | 50 | For VPP we'll use an external 9V battery, just connect 51 | the VCC (+) on the battery to the VPP location when prompted 52 | (helps to have a switch) and the GND (-) to VSS 53 | 54 | This uses the FTDI-D2XX drivers. Get them from 55 | http://www.ftdichip.com/Drivers/D2XX.htm 56 | and follow the readme 57 | 58 | 59 | */ 60 | 61 | 62 | #define FTDI_GREEN_PIN_4 (1<<2) 63 | #define FTDI_ORANGE_PIN_5 (1<<0) 64 | #define FTDI_BROWN_PIN_6 (1<<3) 65 | 66 | #define PIN_PGD (FTDI_GREEN_PIN_4) 67 | #define PIN_PGC (FTDI_ORANGE_PIN_5) 68 | #define PIN_PGM (FTDI_BROWN_PIN_6) 69 | 70 | #define PIN_CLR (PIN_PGM) 71 | #define PIN_PGD_IN (PIN_PGD) 72 | #define PIN_OUT (PIN_PGC|PIN_CLR|PIN_PGD) 73 | 74 | #define PGM_CORE_INST 0 // 0b0000 75 | #define PGM_TABLAT_OUT 2 // 0b0010 76 | #define PGM_TABLE_READ 8 // 0b1000 77 | #define PGM_TABLE_READ_POST_INC 9 // 0b1001 78 | #define PGM_TABLE_READ_POST_DEC 10 // 0b1010 79 | #define PGM_TABLE_READ_PRE_INC 11 // 0b1011 80 | #define PGM_TABLE_WRITE 12 // 0b1100 81 | #define PGM_TABLE_WRITE_POST_INC2 13 // 0b1101 82 | #define PGM_TABLE_WRITE_POST_INC2_PGM 14 // 0b1110 83 | #define PGM_TABLE_WRITE_PGM 15 // 0b1111 84 | 85 | #define BAUD_RATE 1000000 86 | //#define BAUD_RATE 64000 87 | 88 | // Number of registers to read 89 | #define REGS 1536 90 | 91 | // Length of the keys, Master = 8, 3DES = 16 (K1 + K2) 92 | #define KEY_LEN 8 93 | 94 | // Offsets (important ones removed in prod) 95 | #define MASTER 0 96 | #define TDES_K1 0 97 | #define TDES_K2 0 98 | #define LAST_CARD 444 99 | #define LAST_CSN1 393 100 | #define LAST_CSN2 1470 101 | 102 | #include 103 | //#include 104 | #include 105 | #include 106 | #include 107 | 108 | FT_HANDLE m_Handle; 109 | 110 | void help(char *argv[]) { 111 | printf("\t-v\tverbose\n"); 112 | printf("\nExample:\n"); 113 | printf("\t%s\n\n", argv[0]); 114 | } 115 | 116 | void permute(uint8_t *key, uint8_t *res) { 117 | int i,x; 118 | uint8_t p,mask; 119 | 120 | for(i=0;i>i; 123 | for(x=0;x>=1; 125 | if(key[x] & mask) 126 | p|=0x80; 127 | } 128 | res[i] = p; 129 | } 130 | } 131 | 132 | void permute_n(uint8_t *key, uint8_t *res) { 133 | int n=3,i; 134 | while(n--) { 135 | permute(key, res); 136 | for (i=0;i<8;i++) 137 | key[i] = res[i]; 138 | 139 | } 140 | 141 | } 142 | 143 | void shave(uint8_t *key, uint8_t *res) { 144 | int i; 145 | for(i=0;i<8;i++) 146 | res[i] = key[i] & 0xFE; 147 | } 148 | void shave_and_perm(uint8_t *key, uint8_t *res) { 149 | int i; 150 | 151 | printf("\t\t"); 152 | for(i=0;i>= 1; 205 | // shift out PGD data + PGC 206 | *p++ = out; 207 | // shift out PGD only - no PGC 208 | *p++ = out ^ PIN_PGC; 209 | } 210 | // transmit payload data 211 | for (i = 0; i < 16; i++) 212 | { 213 | // keep reset high + PGC 214 | out = PIN_CLR | PIN_PGC; 215 | // get DATA LSB first 216 | if (data & 1) 217 | out |= PIN_PGD; 218 | data >>= 1; 219 | // shift out PGD data + PGC 220 | *p++ = out; 221 | // shift out PGD only - no PGC 222 | *p++ = out ^ PIN_PGC; 223 | } 224 | // all lines to GND except of reset line 225 | *p++ = PIN_CLR; 226 | // for (i=0; i>= 1; 256 | // shift out PGD data + PGC 257 | *p++ = out; 258 | // shift out PGD only - no PGC 259 | *p++ = out ^ PIN_PGC; 260 | } 261 | *p++ = PIN_CLR; 262 | 263 | if ((res = FT_Write (m_Handle, &tx, sizeof (tx), &count)) != FT_OK) 264 | return res; 265 | // printf("FT_WRITE failed!\n"); 266 | if ((res = FT_Read (m_Handle, &tx, sizeof (tx), &count)) != FT_OK) 267 | return res; 268 | // printf("FT_READ failed!\n"); 269 | 270 | out = 0; 271 | for (i = 0; i < 8; i++) { 272 | out = (out >> 1) | ((tx[i * 2 + (1 + 2 * 12)] & PIN_PGD_IN) ? 0x80 : 0); 273 | //out = (out >> 1) | ((tx[i * 2 + (1 + 2 * 12)] & PIN_PGD_IN)) ; 274 | } 275 | return out; 276 | } 277 | 278 | int main(int argc, char *argv[]) { 279 | int ret,i=0, verbose=0; 280 | UCHAR ucMask; 281 | DWORD count; 282 | FT_STATUS ftStatus; 283 | 284 | uint8_t eeprom_data[REGS], key[8], res[8]; 285 | 286 | 287 | printf("iClass EEPROM Dumper\n"); 288 | printf("brad.antoniewicz@foundstone.com\n"); 289 | printf("------------------------------------------------\n"); 290 | 291 | if (argc > 1) { 292 | if((int)argv[1][1] == 'v') 293 | verbose = 1; 294 | else { 295 | help(argv); 296 | return -1; 297 | } 298 | } 299 | 300 | 301 | printf("Connecting to FTDI TTL-232R-5V-WE..."); 302 | 303 | if (FT_Open (0, &m_Handle) == FT_OK) { 304 | 305 | if ((FT_SetBitMode (m_Handle, PIN_OUT, 0x04) == FT_OK) && (FT_SetBaudRate (m_Handle, 1000000) == FT_OK) && ( tick_tx(0x00) == FT_OK ) ) { 306 | printf("Connected!!\n"); 307 | } else { 308 | printf("FAILED!\n"); 309 | FT_Close(m_Handle); 310 | } 311 | } else { 312 | printf("FAILED! (Could not find device)\n"); 313 | printf("You may have to unload the generic FTDI drivers:\n"); 314 | printf("\trmmod ftdi_sio usbserial\n"); 315 | return EXIT_FAILURE; 316 | } 317 | 318 | printf("Checking bitmode..."); 319 | ftStatus = FT_GetBitMode(m_Handle,&ucMask); 320 | 321 | if (ftStatus != FT_OK ) { 322 | printf("Failed!\n"); 323 | } else { 324 | printf("Success!"); 325 | if (verbose) 326 | printf(" - 0x%02x\n",ucMask); 327 | else 328 | printf("\n"); 329 | } 330 | 331 | /* 332 | Hold all lines except VDD Low and wait for 333 | user to raise VPP manually to 9V 334 | */ 335 | printf("\nMake sure at least one card has been read by the reader, then\n"); 336 | printf("connect your FTDI TTL-232R-5V-WE to the reader's ICSP port\n"); 337 | printf("and introduce the VPP power\n\n"); 338 | for(i=20;i>0;i--) { 339 | printf("\033[K\r"); 340 | printf("Sleeping for %d Seconds while you do so....",i); 341 | fflush(stdout); 342 | sleep(1); 343 | } 344 | printf("\n\nStarting EEPROM Dump"); 345 | 346 | /* 347 | This sets FSR0H to 0 348 | */ 349 | // Copy 0 to the working register (MOV literal) 350 | if (verbose) 351 | printf("\n\tMOVLW - Writing PGM_CORE_INST 0x0E00\n"); 352 | ICD_Write(PGM_CORE_INST,0x0E00); 353 | 354 | // Copy working register to FSR0H (MOV WREG) 355 | if (verbose) 356 | printf("\tMOVWF FSR0H - Writing PGM_CORE_INST 0x6EEA\n"); 357 | ICD_Write(PGM_CORE_INST,0x6EEA); 358 | 359 | /* 360 | This sets FSR0L to 0, and according to the bottom of 361 | pg 50 of 39564c.pdf, should increment FSR0H automatically 362 | */ 363 | 364 | // Copy 0 to working register 365 | if (verbose) 366 | printf("\tMOVLW - Writing PGM_CORE_INST 0x0E00\n"); 367 | ICD_Write(PGM_CORE_INST,0x0E00 ); 368 | 369 | // Copy working register to FSR0L 370 | if (verbose) 371 | printf("\tMOVWF FSR0L - Writing PGM_CORE_INST 0x6EE9"); 372 | ICD_Write(PGM_CORE_INST,0x6EE9); 373 | 374 | printf("\n\nDumping (takes ~10 seconds)..\n"); 375 | for (i=1; i