diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 37899f57..ca727644 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -683,7 +683,12 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); - break; + break; + case CMD_VIKING_CLONE_TAG: + CopyViKingtoT55x7(c->arg[0],c->arg[1]); + break; + + #endif #ifdef WITH_HITAG @@ -865,9 +870,19 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_READER_ICLASS_REPLAY: ReaderIClass_Replay(c->arg[0], c->d.asBytes); break; - case CMD_ICLASS_EML_MEMSET: + case CMD_ICLASS_EML_MEMSET: emlSet(c->d.asBytes,c->arg[0], c->arg[1]); break; + case CMD_ICLASS_ISO14443A_WRITE: + IClass_iso14443A_write(c->arg[0],c->d.asBytes); + break; + case CMD_ICLASS_AUTHENTICATION: + IClass_Authentication(c->d.asBytes); + break; + case CMD_ICLASS_CLONE: + IClass_Clone(c->arg[0],c->arg[1],c->d.asBytes); + break; + #endif case CMD_BUFF_CLEAR: diff --git a/armsrc/apps.h b/armsrc/apps.h index b5638ee1..e517c680 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -168,7 +168,10 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain void ReaderIClass(uint8_t arg0); void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); void IClass_iso14443A_GetPublic(uint8_t arg0); - +void IClass_Authentication(uint8_t *MAC); +void IClass_iso14443A_write(uint8_t blockno,uint8_t *data); +void IClass_Clone(uint8_t startblock,uint8_t endblock,uint8_t *data); +void CopyViKingtoT55x7(uint32_t block1,uint32_t block2); // hitag2.h void SnoopHitag(uint32_t type); void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 97c62bb6..9f7dfa87 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1903,131 +1903,57 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { LED_A_OFF(); } - -//2. Create Read method (cut-down from above) based off responses from 1. -// Since we have the MAC could continue to use replay function. -//3. Create Write method -/* -void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) { - uint8_t act_all[] = { 0x0a }; - uint8_t identify[] = { 0x0c }; - uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[]= { 0x88, 0x02 }; - uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; - uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - uint16_t crc = 0; - - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); - - // Reset trace buffer - memset(trace, 0x44, RECV_CMD_OFFSET); - traceLen = 0; - - // Setup SSC - FpgaSetupSsc(); - // Start from off (no field generated) - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); - - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Now give it time to spin up. - // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - SpinDelay(200); - - LED_A_ON(); - - for(int i=0;i<1;i++) { - - if(traceLen > TRACE_SIZE) { - DbpString("Trace full"); - break; - } - - if (BUTTON_PRESS()) break; - - // Send act_all - ReaderTransmitIClass(act_all, 1); - // Card present? - if(ReaderReceiveIClass(resp)) { - ReaderTransmitIClass(identify, 1); - if(ReaderReceiveIClass(resp) == 10) { - // Select card - memcpy(&select[1],resp,8); - ReaderTransmitIClass(select, sizeof(select)); - - if(ReaderReceiveIClass(resp) == 10) { - Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x", - resp[0], resp[1], resp[2], - resp[3], resp[4], resp[5], - resp[6], resp[7]); - } - // Card selected - Dbprintf("Readcheck on Sector 2"); - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - if(ReaderReceiveIClass(resp) == 8) { - Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x", - resp[0], resp[1], resp[2], - resp[3], resp[4], resp[5], - resp[6], resp[7]); - }else return; - Dbprintf("Authenticate"); - //for now replay captured auth (as cc not updated) - memcpy(check+5,MAC,4); - Dbprintf(" AA: %02x %02x %02x %02x", - check[5], check[6], check[7],check[8]); - ReaderTransmitIClass(check, sizeof(check)); - if(ReaderReceiveIClass(resp) == 4) { - Dbprintf(" AR: %02x %02x %02x %02x", - resp[0], resp[1], resp[2],resp[3]); - }else { - Dbprintf("Error: Authentication Fail!"); - return; - } - Dbprintf("Write Block"); - - //read configuration for max block number - read_success=false; - read[1]=1; - uint8_t *blockno=&read[1]; - crc = iclass_crc16((char *)blockno,1); - read[2] = crc >> 8; - read[3] = crc & 0xff; - while(!read_success){ - ReaderTransmitIClass(read, sizeof(read)); - if(ReaderReceiveIClass(resp) == 10) { - read_success=true; - mem=resp[5]; - memory.k16= (mem & 0x80); - memory.book= (mem & 0x20); - memory.k2= (mem & 0x8); - memory.lockauth= (mem & 0x2); - memory.keyaccess= (mem & 0x1); - - } - } - if (memory.k16){ - cardsize=255; - }else cardsize=32; - //check card_size - - memcpy(write+1,blockNo,1); - memcpy(write+2,data,8); - memcpy(write+10,mac,4); - while(!send_success){ - ReaderTransmitIClass(write, sizeof(write)); - if(ReaderReceiveIClass(resp) == 10) { - write_success=true; - } - }// - } - WDT_HIT(); - } - - LED_A_OFF(); -}*/ +void IClass_Authentication(uint8_t *MAC){ + uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t resp[ICLASS_BUFFER_SIZE]; + memcpy(check+5,MAC,4); + + sendCmdGetResponseWithRetries(check, sizeof(check),resp, 8, 5); + // successful +} +void IClass_iso14443A_write(uint8_t blockNo, uint8_t *data) { + uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + write[1] = blockNo; + memcpy(write + 2,data,8); // data + memcpy(write+10,data + 8,4); // mac no + uint8_t r[12]; + + // 0x87 + sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5); + Dbprintf("reply [%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]",r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9],r[10],r[11]); + + if (memcmp(data,r,8) == 0) + Dbprintf("Write block [%02x] ok",blockNo); + else + Dbprintf("Write block [%02x] fail",blockNo); +} +void IClass_Clone(uint8_t startblock,uint8_t endblock,uint8_t *data){ + uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t r[12]; + int i; + int written = 0; + int total_block = (endblock - startblock) + 1; + for (i = 0; i < total_block;i++){ + // block number + write[0] = 0x87; + write[1] = i + startblock; + // data + memcpy(write + 2,data + (i * 12),8); + // mac number + memcpy(write + 10,data + ((i * 12) + 8), 4); + sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5); + + if (memcmp(write + 2,r,8) == 0){ + Dbprintf("Write block [%02x] ok",i + 6); + written++; + } + else + Dbprintf("Write block [%02x] fail",i + 6); + } + if (written == total_block) + Dbprintf("Clone complete"); + else + Dbprintf("Clone incomplete"); + +} diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 188d7280..75eaaa86 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2062,3 +2062,14 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } +void CopyViKingtoT55x7(uint32_t block1,uint32_t block2) +{ + LED_D_ON(); + T55xxWriteBlock(block1,1,0,0); + T55xxWriteBlock(block2,2,0,0); + + T55xxWriteBlock(T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 2 << T5555_MAXBLOCK_SHIFT,0,0,1); + LED_D_OFF(); + DbpString("DONE!"); +} + diff --git a/client/.history b/client/.history new file mode 100644 index 00000000..66787acd --- /dev/null +++ b/client/.history @@ -0,0 +1 @@ +lf diff --git a/client/Makefile b/client/Makefile index 15b1cbca..bee9a336 100644 --- a/client/Makefile +++ b/client/Makefile @@ -93,6 +93,7 @@ CMDSRCS = nonce2key/crapto1.c\ cmdlfem4x.c \ cmdlfhitag.c \ cmdlfti.c \ + cmdlfviking.c\ cmdparser.c \ cmdmain.c \ cmdlft55xx.c \ @@ -104,7 +105,7 @@ CMDSRCS = nonce2key/crapto1.c\ aes.c\ protocols.c\ sha1.c\ - + ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED #-DDEBUG -Dverbose=1 diff --git a/client/cmddata.c b/client/cmddata.c index bec1b5aa..c4bae05f 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1870,6 +1870,53 @@ int CmdRawDemod(const char *Cmd) return ans; } +int AmVikingDecode(const uint8_t *id){ + // searching the buffer for the id + uint8_t id_bits[32]; + // convert 4 bytes of id to 32 bits present in 32 bytes data; + bytes_to_bits(id,4,id_bits,sizeof(id_bits)); + printf("binary : "); + print_arraybinary(id_bits,sizeof(id_bits)); + printf("\n"); + size_t idx = 0; + size_t BitLen = DemodBufferLen; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + memcpy(BitStream, DemodBuffer, BitLen); + + if (VikingDecode(BitStream,BitLen,&idx,id_bits,sizeof(id_bits)) == 1) + { + setDemodBuf(BitStream,64, idx); + printf("Found Viking tag\n"); + CmdPrintDemodBuff("x"); + } + else + { + printf("Not found Viking tag\n"); + } + return 0; +} +int AMVikingDemod(const uint8_t *id){ + // demod am clock 32 fail + if (!ASKDemod("32",g_debugMode,false,1)) + return 0; + // search for the card id from bitstream. + return AmVikingDecode(id); +} +//by Gusto +// takes 1 argument <8 bytes of Hex number on the card +// print binary found and saves in grapbuffer for further commands +int CmdAMVikingDemod(const char *Cmd){ + uint8_t id[4]; + if (param_gethex(Cmd,0,id,8) == 1) + { + PrintAndLog("Usage: data vikingdemod CardID 8 bytes of hex number"); + return 0; + } + printf("Card ID : %02X%02X%02X%02X\n",id[0],id[1],id[2],id[3]); + // try to demod AMViking + return AMVikingDemod(id); +} + int CmdGrid(const char *Cmd) { sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); @@ -2279,6 +2326,7 @@ static command_t CommandTable[] = {"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"}, {"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"}, {"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"}, + {"vikingdemod", CmdAMVikingDemod, 1, "Demodulate a Viking AM tag from GraphBuffer"}, //{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"}, {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"}, {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"}, diff --git a/client/cmddata.h b/client/cmddata.h index fcc51a6b..c70f938e 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -67,7 +67,8 @@ int PSKDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose); void printEM410x(uint32_t hi, uint64_t id); int getSamples(const char *Cmd, bool silent); - +int AMVikingDemod(const uint8_t *cardid); +int CmdAMVikingDemod(const char *cmd); #define MAX_DEMOD_BUF_LEN (1024*128) extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c old mode 100644 new mode 100755 index 824aaa36..5ee25144 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -31,9 +31,14 @@ #include "loclass/fileutils.h" #include "protocols.h" #include "usb_cmd.h" - +typedef struct iclass_block { + uint8_t d[8]; +} iclass_block_t; static int CmdHelp(const char *Cmd); - +static uint8_t GLOBAL_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +static uint8_t HS_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +static uint8_t BLANK_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +static bool HS_KEY_LOAD = false; int xorbits_8(uint8_t val) { uint8_t res = val ^ (val >> 1); //1st pass @@ -42,7 +47,117 @@ int xorbits_8(uint8_t val) res = res ^ (res >> 4); // 4th pass return res & 1; } +void CmdHFiClass_printkey(const char* keyname,const uint8_t *key){ + printf("%s : %02X%02X%02X%02X%02X%02X%02X%02X\n",keyname,key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7]); +} +int readKeyfile(const char *filename, size_t len, uint8_t* buffer) +{ + FILE *f = fopen(filename, "rb"); + if(!f) { + PrintAndLog("Failed to read from file '%s'", filename); + return 1; + } + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + size_t bytes_read = fread(buffer, 1, len, f); + fclose(f); + if(fsize != len) + { + PrintAndLog("Warning, file size is %d, expected %d", fsize, len); + return 1; + } + if(bytes_read != len) + { + PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len); + return 1; + } + return 0; +} +int usage_iclass_readkeyfile(){ + printf("usage: hf iclass readkeyfile \n"); + return 0; +} +int CmdHFiClassReadKeyFile(const char *Cmd){ + uint8_t key[8]; + if ( (strlen(Cmd) < 1) || (readKeyfile(Cmd,sizeof(key),key) != 0)) { + return usage_iclass_readkeyfile(); + } + CmdHFiClass_printkey("Key ",key); + return 0; +} +int usage_iclass_savekeyfile(){ + printf("usage: hf iclass writekeyfile filename\n"); + return 0; +} +int CmdHFiClassSaveKeyFile(const char *Cmd){ + char filename[50]; + uint8_t key[8]; + FILE *file; + if (param_gethex(Cmd, 0, key, 16)) + { + PrintAndLog("KEY must include 16 HEX symbols"); + return 1; + } + if (param_getstr(Cmd,1,filename) < 1) + return usage_iclass_savekeyfile(); + + file = fopen(filename,"wb"); + + if (file == NULL) { + printf("error opening file %s\n",filename); + return 0; + } + if (fwrite(&key,sizeof(key),1,file)) + printf("write key to file was successful\n"); + else + printf("write key to file was fail\n"); + fclose(file); + return 0; +} + +int CmdHFiClass_SendAuthentication(uint8_t *MAC){ + UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}}; + memcpy(d.d.asBytes,MAC, 4); + SendCommand(&d); + return 0; + +} +int CmdHFiClass_SendACK(uint8_t *CSN,uint8_t *CCNR) { + + UsbCommand resp; + UsbCommand c = {CMD_READER_ICLASS, {0}}; + c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC; + SendCommand(&c); + + if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) + { + PrintAndLog("Command execute timeout"); + return 1; + } + + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t * data = resp.d.asBytes; + + memcpy(CSN,data,8); + memcpy(CCNR,data+16,8); + + if(isOK <= 1){ + PrintAndLog("Failed to obtain CC! Aborting"); + return 1; + } + + PrintAndLog("CSN: %s",sprint_hex(CSN,8)); + return 0; +} +int CmdHFiClass_SendReadBlock(uint8_t blockno,uint8_t *rdata){ + UsbCommand d = {CMD_ICLASS_READBLOCK, {blockno}}; + memcpy(d.d.asBytes,rdata,sizeof(uint8_t *)); + SendCommand(&d); + + return 0; +} int CmdHFiClassList(const char *Cmd) { PrintAndLog("Deprecated command, use 'hf list iclass' instead"); @@ -230,162 +345,124 @@ int CmdHFiClassReader_Replay(const char *Cmd) return 0; } - +int usage_hf_iclass_dump(){ + PrintAndLog("Usage: hf iclass dump [e]"); + PrintAndLog(" Key - A 16 byte master key"); + PrintAndLog(" e - If 'e' is specified, HS_KEY will be used otherwise standard key"); + return 0; +} int CmdHFiClassReader_Dump(const char *Cmd) { - uint8_t readerType = 0; - uint8_t MAC[4]={0x00,0x00,0x00,0x00}; - uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t keytable[128] = {0}; - int elite = 0; - uint8_t *used_key; - int i; - if (strlen(Cmd)<1) - { - PrintAndLog("Usage: hf iclass dump [e]"); - PrintAndLog(" Key - A 16 byte master key"); - PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte"); - PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack"); - PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format"); - PrintAndLog(" sample: hf iclass dump 0011223344556677"); + uint8_t readerType = 0; + uint8_t MAC[4]={0x00,0x00,0x00,0x00}; + uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t keytable[128] = {0}; + int elite = 0; + uint8_t *used_key; + int i; + + if (param_getchar(Cmd, 0) == 'e') + { + PrintAndLog("Elite switch on"); + elite = 1; + memcpy(KEY,HS_KEY,sizeof(KEY)); + //calc h2 + hash2(KEY, keytable); + //printarr_human_readable("keytable", keytable, 128); + } + else + memcpy(KEY,GLOBAL_KEY,sizeof(KEY)); + + UsbCommand resp; + uint8_t key_sel[8] = {0}; + uint8_t key_sel_p[8] = { 0 }; + // send ACK + if (CmdHFiClass_SendACK(CSN,CCNR) != 0) + return 1; - return 0; - } - - if (param_gethex(Cmd, 0, KEY, 16)) - { - PrintAndLog("KEY must include 16 HEX symbols"); - return 1; - } - - if (param_getchar(Cmd, 1) == 'e') - { - PrintAndLog("Elite switch on"); - elite = 1; - - //calc h2 - hash2(KEY, keytable); - printarr_human_readable("keytable", keytable, 128); - - } - - UsbCommand resp; - uint8_t key_sel[8] = {0}; - uint8_t key_sel_p[8] = { 0 }; - - UsbCommand c = {CMD_READER_ICLASS, {0}}; - c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC; - SendCommand(&c); - - - - if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) - { - PrintAndLog("Command execute timeout"); - return 0; - } - - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; - - memcpy(CSN,data,8); - memcpy(CCNR,data+16,8); - - PrintAndLog("isOk:%02x", isOK); - - if(isOK > 0) - { - PrintAndLog("CSN: %s",sprint_hex(CSN,8)); - } - if(isOK <= 1){ - PrintAndLog("Failed to obtain CC! Aborting"); - return 0; - } - //Status 2 or higher - - if(elite) - { - //Get the key index (hash1) - uint8_t key_index[8] = {0}; - - hash1(CSN, key_index); - printvar("hash1", key_index,8); - for(i = 0; i < 8 ; i++) - key_sel[i] = keytable[key_index[i]] & 0xFF; - PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); - printvar("k_sel", key_sel,8); - //Permute from iclass format to standard format - permutekey_rev(key_sel,key_sel_p); - used_key = key_sel_p; - }else{ - used_key = KEY; - } - - PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); - printvar("Used key",used_key,8); - diversifyKey(CSN,used_key, div_key); - PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); - printvar("Div key", div_key, 8); - printvar("CC_NR:",CCNR,12); - doMAC(CCNR,div_key, MAC); - printvar("MAC", MAC, 4); - - uint8_t iclass_data[32000] = {0}; - uint32_t iclass_datalen = 0; - uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete - - UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}}; - memcpy(d.d.asBytes, MAC, 4); - clearCommandBuffer(); - SendCommand(&d); - PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort..."); - while (true) { - printf("."); - if (ukbhit()) { - getchar(); - printf("\naborted via keyboard!\n"); - break; - } - if(WaitForResponseTimeout(CMD_ACK,&resp,4500)) - { - uint32_t dataLength = resp.arg[0]; - iclass_blocksFailed |= resp.arg[1]; - if(dataLength > 0) - { - PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen); - memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength); - iclass_datalen += dataLength; - }else - {//Last transfer, datalength 0 means the dump is finished - PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen); - if(iclass_blocksFailed) - { - PrintAndLog("OBS! Some blocks failed to be dumped correctly!"); - } - if(iclass_datalen > 0) - { - char filename[100] = {0}; - //create a preferred filename - snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", - CSN[0],CSN[1],CSN[2],CSN[3], - CSN[4],CSN[5],CSN[6],CSN[7]); - //Place the div_key in block 3 - memcpy(iclass_data+(3*8), div_key, 8); - saveFile(filename,"bin",iclass_data, iclass_datalen ); - } - //Aaaand we're finished - return 0; - } - } - } - - - return 0; + //Status 2 or higher + + if(elite) + { + //Get the key index (hash1) + uint8_t key_index[8] = {0}; + + hash1(CSN, key_index); + //printvar("hash1", key_index,8); + for(i = 0; i < 8 ; i++) + key_sel[i] = keytable[key_index[i]] & 0xFF; + //PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); + //printvar("k_sel", key_sel,8); + //Permute from iclass format to standard format + permutekey_rev(key_sel,key_sel_p); + used_key = key_sel_p; + }else{ + used_key = KEY; + } + + //PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); + //printvar("Used key",used_key,8); + diversifyKey(CSN,used_key, div_key); + //PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); + //printvar("Div key", div_key, 8); + //printvar("CC_NR:",CCNR,12); + doMAC(CCNR,div_key, MAC); + //printvar("MAC", MAC, 4); + + uint8_t iclass_data[32000] = {0}; + uint32_t iclass_datalen = 0; + uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete + + UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}}; + memcpy(d.d.asBytes, MAC, 4); + clearCommandBuffer(); + SendCommand(&d); + PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort..."); + while (true) { + printf("."); + if (ukbhit()) { + getchar(); + printf("\naborted via keyboard!\n"); + break; + } + if(WaitForResponseTimeout(CMD_ACK,&resp,4500)) + { + uint32_t dataLength = resp.arg[0]; + iclass_blocksFailed |= resp.arg[1]; + if(dataLength > 0) + { + PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen); + memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength); + iclass_datalen += dataLength; + }else + {//Last transfer, datalength 0 means the dump is finished + PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen); + if(iclass_blocksFailed) + { + PrintAndLog("OBS! Some blocks failed to be dumped correctly!"); + } + if(iclass_datalen > 0) + { + char filename[100] = {0}; + //create a preferred filename + snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", + CSN[0],CSN[1],CSN[2],CSN[3], + CSN[4],CSN[5],CSN[6],CSN[7]); + //Place the div_key in block 3 + memcpy(iclass_data+(3*8), div_key, 8); + saveFile(filename,"bin",iclass_data, iclass_datalen ); + } + //Aaaand we're finished + return 0; + } + } + } + return 0; } int hf_iclass_eload_usage() @@ -477,31 +554,6 @@ int usage_hf_iclass_decrypt() return 1; } -int readKeyfile(const char *filename, size_t len, uint8_t* buffer) -{ - FILE *f = fopen(filename, "rb"); - if(!f) { - PrintAndLog("Failed to read from file '%s'", filename); - return 1; - } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - size_t bytes_read = fread(buffer, 1, len, f); - fclose(f); - if(fsize != len) - { - PrintAndLog("Warning, file size is %d, expected %d", fsize, len); - return 1; - } - if(bytes_read != len) - { - PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len); - return 1; - } - return 0; -} - int CmdHFiClassDecrypt(const char *Cmd) { uint8_t key[16] = { 0 }; @@ -559,83 +611,51 @@ int CmdHFiClassDecrypt(const char *Cmd) return 0; } - +void Calc_wb_mac(uint8_t blockno,uint8_t *data,uint8_t *div_key,uint8_t MAC[4]){ + uint8_t WB[9]; + WB[0] = blockno; + memcpy(WB + 1,data,8); + // do mac 9 bytes + doMAC_N(WB,sizeof(WB),div_key,MAC); +} int CmdHFiClass_iso14443A_write(const char *Cmd) { - uint8_t readerType = 0; - uint8_t MAC[4]={0x00,0x00,0x00,0x00}; - uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - - uint8_t blockNo=0; + uint8_t blockno=0; uint8_t bldata[8]={0}; + uint8_t MAC[4]={0x00,0x00,0x00,0x00}; - if (strlen(Cmd)<3) - { - PrintAndLog("Usage: hf iclass write "); - PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA"); - return 0; - } + uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - if (param_gethex(Cmd, 0, KEY, 16)) - { - PrintAndLog("KEY must include 16 HEX symbols"); - return 1; - } + if (param_gethex(Cmd, 0,&blockno, 2)) + { + PrintAndLog("Block No must include 2 HEX symbols"); + return 1; + } + if (param_gethex(Cmd, 1, bldata, 16)) + { + PrintAndLog("Block data must include 16 HEX symbols"); + return 1; + } + // tell the reader to send ACK and get CSN + CCNR + if (CmdHFiClass_SendACK(CSN,CCNR) != 0) + return 1; + + memcpy(KEY,GLOBAL_KEY,sizeof(KEY)); + diversifyKey(CSN,KEY, div_key); + doMAC(CCNR,div_key, MAC); + // send authentication + CmdHFiClass_SendAuthentication(MAC); + // send write command + Calc_wb_mac(blockno,bldata,div_key,MAC); + UsbCommand w = {CMD_ICLASS_ISO14443A_WRITE, {blockno}}; + memcpy(w.d.asBytes, bldata, 8); + memcpy(w.d.asBytes + 8,MAC, 4); - blockNo = param_get8(Cmd, 1); - if (blockNo>32) - { - PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!"); - return 1; - } - if (param_gethex(Cmd, 2, bldata, 8)) - { - PrintAndLog("Block data must include 8 HEX symbols"); - return 1; - } - - UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}}; - SendCommand(&c); - UsbCommand resp; - - if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; - - memcpy(CSN,data,8); - memcpy(CCNR,data+8,8); - PrintAndLog("DEBUG: %s",sprint_hex(CSN,8)); - PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8)); - PrintAndLog("isOk:%02x", isOK); - } else { - PrintAndLog("Command execute timeout"); - } - - diversifyKey(CSN,KEY, div_key); - - PrintAndLog("Div Key: %s",sprint_hex(div_key,8)); - doMAC(CCNR, div_key, MAC); - - UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}}; - memcpy(c2.d.asBytes, bldata, 8); - memcpy(c2.d.asBytes+8, MAC, 4); - SendCommand(&c2); - - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; - - if (isOK) - PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4)); - else - PrintAndLog("isOk:%02x", isOK); - } else { - PrintAndLog("Command execute timeout"); - } - return 0; + SendCommand(&w); + return 0; } int CmdHFiClass_loclass(const char *Cmd) { @@ -682,23 +702,406 @@ int CmdHFiClass_loclass(const char *Cmd) return 0; } - -static command_t CommandTable[] = +int usage_hf_iclass_readtagfile(){ + PrintAndLog("Usage: hf iclass readtagfile "); + return 1; +} +void printIclassDumpContents(uint8_t* iclass_dump,uint8_t startblock,uint8_t endblock,size_t filesize){ + uint8_t blockdata[8]; + uint8_t mem_config; + memcpy(&mem_config, iclass_dump + 13,1); + uint8_t maxmemcount; + uint8_t filemaxblock = filesize / 8; + if (mem_config == 0x80) + maxmemcount = 255; + else + maxmemcount = 32; + + if (startblock == 0) + startblock = 6; + if ((endblock > maxmemcount) || (endblock == 0)) + endblock = maxmemcount; + if (endblock > filemaxblock) + endblock = filemaxblock; + int i = startblock; + int j; + while (i < endblock){ + printf("block[%02x]: ",i); + memcpy(blockdata,iclass_dump + (i * 8),8); + for (j = 0;j < 8;j++) + printf("%02x",blockdata[j]); + printf("\n"); + i++; + } + if ((i < filemaxblock) && (i < maxmemcount)){ + printf("block[%02x]: ",i); + memcpy(blockdata,iclass_dump + (i * 8),8); + for (j = 0;j < 8;j++) + printf("%02x",blockdata[j]); + printf("\n"); + } +} +int CmdHFiClassReadTagFile(const char *Cmd) { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"}, - {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, - {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, - {"reader",CmdHFiClassReader, 0, "Read an iClass tag"}, - {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, - {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, -// {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, - {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"}, - {"eload", CmdHFiClassELoad, 0, "[experimental] Load data into iclass emulator memory"}, - {"decrypt", CmdHFiClassDecrypt, 1, "Decrypt tagdump" }, - {NULL, NULL, 0, NULL} -}; + int startblock = 0; + int endblock = 0; + char tempnum[5]; + FILE *f; + char filename[FILE_PATH_SIZE]; + if (param_getstr(Cmd, 0, filename) < 1) + return usage_hf_iclass_readtagfile(); + if (param_getstr(Cmd,1,(char *)&tempnum) < 1) + startblock = 0; + else + sscanf(tempnum,"%d",&startblock); + + if (param_getstr(Cmd,2,(char *)&tempnum) < 1) + endblock = 0; + else + sscanf(tempnum,"%d",&endblock); + // file handling and reading + f = fopen(filename,"rb"); + if(!f) { + PrintAndLog("Failed to read from file '%s'", filename); + return 1; + } + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + uint8_t *dump = malloc(fsize); + + + size_t bytes_read = fread(dump, 1, fsize, f); + fclose(f); + uint8_t *csn = dump; + printf("CSN : %02x %02x %02x %02x %02x %02x %02x %02x\n",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]); +// printIclassDumpInfo(dump); + printIclassDumpContents(dump,startblock,endblock,bytes_read); + free(dump); + return 0; +} +int usage_hf_iclass_calckey(){ + PrintAndLog("error please load ekey"); + return 1; +} +uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv){ + uint64_t new_div = 0x00; + new_div ^= sdiv; + new_div ^= hdiv; + return new_div; +} +uint64_t hexarray_to_uint64(uint8_t *key){ + char temp[17]; + uint64_t uint_key; + for (int i = 0;i < 8;i++) + sprintf(&temp[(i *2)],"%02X",key[i]); + temp[16] = '\0'; + if (sscanf(temp,"%016llX",&uint_key) < 1) + return 0; + return uint_key; +} +int CmdHFiClassCalcEKey(const char *Cmd){ + + uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t std_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t elite_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t keytable[128] = {0}; + uint8_t key_index[8] = {0}; + uint64_t new_div_key; + uint64_t i_elite_div_key; + uint64_t i_std_div_key; + int i; + if (!HS_KEY_LOAD) + return usage_hf_iclass_calckey(); + + hash2(HS_KEY, keytable); + + UsbCommand resp; + uint8_t key_sel[8] = {0}; + uint8_t key_sel_p[8] = { 0 }; + + UsbCommand c = {CMD_READER_ICLASS, {0}}; + c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC; + SendCommand(&c); + + if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) + { + PrintAndLog("Command execute timeout"); + return 0; + } + + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t * data = resp.d.asBytes; + + memcpy(CSN,data,8); + +// PrintAndLog("isOk:%02x", isOK); + + if(isOK > 0) + { + PrintAndLog("CSN: %s",sprint_hex(CSN,8)); + } + if(isOK <= 1){ + PrintAndLog("Failed to obtain CC! Aborting"); + return 0; + } + diversifyKey(CSN, GLOBAL_KEY, std_div_key); + +// printvar("(S)Div key", std_div_key, 8); + hash1(CSN, key_index); + for(i = 0; i < 8 ; i++) + key_sel[i] = keytable[key_index[i]] & 0xFF; + + //Permute from iclass format to standard format + permutekey_rev(key_sel,key_sel_p); + diversifyKey(CSN,key_sel_p, elite_div_key); +// printvar("(E)Div key", elite_div_key, 8); + i_elite_div_key = hexarray_to_uint64(elite_div_key); + i_std_div_key = hexarray_to_uint64(std_div_key); + new_div_key = xorcheck(i_std_div_key,i_elite_div_key); + printf("(E)Div key : %016llx\n",new_div_key); + return 0; + +} +int usage_hf_iclass_load(){ + PrintAndLog("Usage: hf iclass load "); + PrintAndLog(" sample: hf iclass write iclass_tagdump-121345.bin 6 19"); + return -1; +} +// load data from tag file and write to another iclass tag +int CmdHFiClass_load(const char *Cmd){ + + if (strlen(Cmd) < 3) + return usage_hf_iclass_load(); + int startblock = 0; + int endblock = 0; + char tempnum[5]; + uint8_t mem_config; + FILE *f; + char filename[FILE_PATH_SIZE]; + if (param_getstr(Cmd, 0, filename) < 1) + return usage_hf_iclass_load(); + + if (param_getstr(Cmd,1,(char *)&tempnum) < 1) + startblock = 6; + else + sscanf(tempnum,"%d",&startblock); + + if (param_getstr(Cmd,2,(char *)&tempnum) < 1) + endblock = 0; + else + sscanf(tempnum,"%d",&endblock); + + // file handling and reading + f = fopen(filename,"rb"); + if(!f) { + PrintAndLog("Failed to read from file '%s'", filename); + return 1; + } + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + uint8_t *dump = malloc(fsize); + + size_t bytes_read = fread(dump, 1, fsize, f); + fclose(f); + + memcpy(&mem_config,dump + 13,1); + uint8_t maxmemcount; + + uint8_t filemaxblock = bytes_read / 8; + if (mem_config == 0x80) + maxmemcount = 255; + else + maxmemcount = 32; + + if (startblock == 0) + startblock = 6; + if ((endblock > maxmemcount) || (endblock == 0)) + endblock = maxmemcount; + if (endblock > filemaxblock) + endblock = filemaxblock; + + return 0; +} +int CmdHFIClassReadBlock(const char *Cmd){ + uint8_t blockno=0; + uint8_t MAC[4]={0x00,0x00,0x00,0x00}; + uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + + if (param_gethex(Cmd, 0,&blockno, 2)) + { + PrintAndLog("Block No must include 2 HEX symbols"); + return 1; + } + // tell the reader to send ACK and get CSN + CCNR + if (CmdHFiClass_SendACK(CSN,CCNR) != 0) + return 1; + + memcpy(KEY,GLOBAL_KEY,sizeof(KEY)); + // PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); + // printvar("Used key",KEY,8); + diversifyKey(CSN,KEY, div_key); + // PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); + // printvar("Div key", div_key, 8); + // printvar("CC_NR:",CCNR,8); + doMAC(CCNR,div_key, MAC); + // printvar("MAC", MAC, 4); + CmdHFiClass_SendAuthentication(MAC); + + // not yet implement + + return 0; +} + + +int CmdHFiClassCloneTag_Usage(){ + PrintAndLog("Usage: hf iclass clone -e "); + PrintAndLog(" sample: hf iclass clone iclass_tagdump-121345.bin 6 19 -e 1122334455667788"); + return -1; +} +int CmdHFiClassCloneTag(const char *Cmd){ + if (strlen(Cmd) < 3) + return CmdHFiClassCloneTag_Usage(); + + int startblock = 0; + int endblock = 0; + char tempnum[5]; + FILE *f; + + iclass_block_t tag_data[26]; + uint8_t MAC[4]={0x00,0x00,0x00,0x00}; + uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + + char filename[FILE_PATH_SIZE]; + // get tagfile parameter + if (param_getstr(Cmd, 0, filename) < 1) + return usage_hf_iclass_load(); + // get start block parameter + if (param_getstr(Cmd,1,(char *)&tempnum) < 1) + startblock = 6; + else + sscanf(tempnum,"%x",&startblock); + // get end block parameter + if (param_getstr(Cmd,2,(char *)&tempnum) < 1) + endblock = 0; + else + sscanf(tempnum,"%x",&endblock); + + + // file handling and reading + f = fopen(filename,"rb"); + if(!f) { + PrintAndLog("Failed to read from file '%s'", filename); + return 1; + } + + // now read data from the file from block 6 --- 19 + // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data + // then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time, + // else we have to create a share memory + int i; + fseek(f,6*8,SEEK_SET); + fread(tag_data,sizeof(iclass_block_t),32 - 6,f); + for (i = 0;i < 32 - 6; i++){ + printf("block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]\n",i + 6,tag_data[i].d[0],tag_data[i].d[1],tag_data[i].d[2],tag_data[i].d[3],tag_data[i].d[4],tag_data[i].d[5],tag_data[i].d[6],tag_data[i].d[7]); + } + + // tell the reader to send ACK and get CSN + CCNR + if (CmdHFiClass_SendACK(CSN,CCNR) != 0) + return 1; + + memcpy(KEY,GLOBAL_KEY,sizeof(KEY)); + // PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); + // printvar("Used key",KEY,8); + diversifyKey(CSN,KEY, div_key); + // PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); + // printvar("Div key", div_key, 8); + // printvar("CC_NR:",CCNR,8); + doMAC(CCNR,div_key, MAC); + // printvar("MAC", MAC, 4); + + // now authentication with the card + CmdHFiClass_SendAuthentication(MAC); + + + // everythings is ready now + UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}}; + uint8_t *ptr; + // calculate all mac for every the block we will write + for (i = startblock;i <= endblock;i++){ + Calc_wb_mac(i,tag_data[i - 6].d,div_key,MAC); + // usb command d start pointer = d + (i - 6) * 12 + // memcpy(pointer,tag_data[i - 6],8) 8 bytes + // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes; + // next one + ptr = w.d.asBytes + (i - 6) * 12; + memcpy(ptr, &(tag_data[i - 6].d[0]), 8); + memcpy(ptr + 8,MAC, 4); + } + uint8_t p[12]; + for (i = 0; i <= endblock - startblock;i++){ + memcpy(p,w.d.asBytes + (i * 12),12); + printf("block [%02x]",i + 6); + printf(" [%02x%02x%02x%02x%02x%02x%02x%02x]",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]); + printf(" MAC [%02x%02x%02x%02x]\n",p[8],p[9],p[10],p[11]); + } + SendCommand(&w); + return 0; +} +int CmdHFiClassEKey_usage(){ + PrintAndLog(" Usage: hf iclass ekey [filename] to load the key"); + PrintAndLog("Sample: hf iclass ekey helloworld.key [load key from file]"); + PrintAndLog("Sample: hf iclass ekey [show the current ekey]"); + return -1; +} +int CmdHFiClassEKey(const char *Cmd){ + if (strlen(Cmd) > 1) + { + if (readKeyfile(Cmd,sizeof(HS_KEY),HS_KEY) != 0) + { + HS_KEY_LOAD = false; + memcpy(HS_KEY,BLANK_KEY,sizeof(BLANK_KEY)); + return CmdHFiClassEKey_usage(); + } + HS_KEY_LOAD = true; + } + else + CmdHFiClass_printkey("HS Key",HS_KEY); + return 0; +} +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"}, + {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, + {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, + {"reader", CmdHFiClassReader, 0, "Read an iClass tag"}, + {"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, + {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, + {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, + {"read", CmdHFIClassReadBlock, 0, "Authenticate and Read iClass block"}, + {"load", CmdHFiClass_load, 0, "Load from tagfile to iclass card"}, + {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"}, + {"eload", CmdHFiClassELoad, 0, "[experimental] Load data into iclass emulator memory"}, + {"decrypt", CmdHFiClassDecrypt, 1, "Decrypt tagdump" }, + {"readtagfile", CmdHFiClassReadTagFile, 1, "Display Content from tagfile"}, + {"ediv", CmdHFiClassCalcEKey, 0, "Give Diversify key for this card to write to block 3"}, + {"readkey", CmdHFiClassReadKeyFile, 1, "Read and display key from file"}, + {"savekey", CmdHFiClassSaveKeyFile, 1, "Write key to file"}, + {"clone", CmdHFiClassCloneTag, 0, "Clone tag"}, + {"ekey", CmdHFiClassEKey, 1, "Load HS key from file or show current HS Key"}, + {NULL, NULL, 0, NULL} +}; int CmdHFiClass(const char *Cmd) { CmdsParse(CommandTable, Cmd); diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h old mode 100644 new mode 100755 index 30c6a8a7..abcb48a9 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -1,3 +1,5 @@ +// version 2.1.0 +// add readkeyfile,writekeyfile,modify dump,iso write and calcEkey functions. //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh // Copyright (C) 2011 Gerhard de Koning Gans @@ -20,5 +22,10 @@ int CmdHFiClassList(const char *Cmd); int HFiClassReader(const char *Cmd, bool loop, bool verbose); int CmdHFiClassReader(const char *Cmd); int CmdHFiClassReader_Replay(const char *Cmd); - +int CmdHFiClassReadKeyFile(const char *filename); +int CmdHFiClassWriteKeyFile(const char *Cmd); +int CmdHFiClass_iso14443A_write(const char *Cmd); +int CmdHFiClassCalcEKey(const char *Cmd); +int CmdHFiClassRestore(const char *cmd); +int CmdHFiClass_TestMac(const char *Cmd); #endif diff --git a/client/cmdlf.c b/client/cmdlf.c index 6dae5164..0569ea85 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -30,7 +30,7 @@ #include "cmdlfpcf7931.h" #include "cmdlfio.h" #include "lfdemod.h" - +#include "cmdlfviking.h" static int CmdHelp(const char *Cmd); /* send a command before reading */ @@ -1148,6 +1148,7 @@ static command_t CommandTable[] = {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"}, + {"viking", CmdLFViking, 1, "{Viking RFIDs..}"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c new file mode 100755 index 00000000..d20f2560 --- /dev/null +++ b/client/cmdlfviking.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "util.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "cmdlfviking.h" +#include "lfdemod.h" +static int CmdHelp(const char *Cmd); +int CmdVikingDemod(const char *Cmd) +{ + uint8_t id[4]; + if (param_gethex(Cmd,0,id,8) == 1) + { + PrintAndLog("Usage: lf viking demod "); + return 0; + } + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {false,0,0}}; + SendCommand(&c); + WaitForResponse(CMD_ACK,NULL); + getSamples("40000",true); + // try to demod AMViking + return AMVikingDemod(id); +} +int CmdVikingClone(const char *Cmd) +{ + uint32_t b1,b2; + // get the tag number 64 bits (8 bytes) in hex + uint8_t id[8]; + if (param_gethex(Cmd,0,id,16) == 1) + { + PrintAndLog("Usage: lf viking clone "); + return 0; + } + b1 = bytes_to_num(id,sizeof(uint32_t)); + b2 = bytes_to_num(id + sizeof(uint32_t),sizeof(uint32_t)); + UsbCommand c = {CMD_VIKING_CLONE_TAG,{b1,b2}}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod",CmdVikingDemod ,1, "<8 digits tag id> -- Extract tag data"}, + {"clone", CmdVikingClone, 1, "<16 digits card data> clone viking tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFViking(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h new file mode 100755 index 00000000..469a2b7b --- /dev/null +++ b/client/cmdlfviking.h @@ -0,0 +1,7 @@ +#ifndef CMDLFVIKING_H__ +#define CMDLFVIKING_H__ +int CmdLFViking(const char *Cmd); +int CmdVikingDemod(const char *Cmd); +int CmdVikingClone(const char *Cmd); +#endif + diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 7c9cc873..2aae093d 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -241,6 +241,27 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) //free(cc_nr); return; } +void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4]) +{ + uint8_t *cc_nr; + uint8_t div_key[8]; + cc_nr = (uint8_t*) malloc(cc_nr_size); + + memcpy(cc_nr,cc_nr_p,cc_nr_size); + memcpy(div_key,div_key_p,8); + + reverse_arraybytes(cc_nr,cc_nr_size); + BitstreamIn bitstream = {cc_nr,cc_nr_size * 8,0}; + uint8_t dest []= {0,0,0,0,0,0,0,0}; + BitstreamOut out = { dest, sizeof(dest)*8, 0 }; + MAC(div_key,bitstream, out); + //The output MAC must also be reversed + reverse_arraybytes(dest, sizeof(dest)); + memcpy(mac, dest, 4); + free(cc_nr); + return; +} + #ifndef ON_DEVICE int testMAC() { diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index bdea9432..24e86851 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -42,6 +42,8 @@ #include void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); +void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4]); + #ifndef ON_DEVICE int testMAC(); #endif diff --git a/client/util.c b/client/util.c index 9f2142c6..1660715e 100644 --- a/client/util.c +++ b/client/util.c @@ -453,3 +453,32 @@ void xor(unsigned char *dst, unsigned char *src, size_t len) { int32_t le24toh (uint8_t data[3]) { return (data[2] << 16) | (data[1] << 8) | data[0]; } +size_t bytes_to_bits(const uint8_t *src,size_t src_size,uint8_t *des,size_t des_size){ + int i,j,k; + int count = 0; + // check src_size and des_size + if ((src_size * 8) > des_size) + return -1; + // convert 1 bytes to 8 bits at the time + for (j = 0;j < src_size;j++){ + for (i = 0;i < 8;i++){ + k = src[j] >> i; + if (k & 1) + *(des + (j * 8) + (7 - i)) = 1; + else + *(des + (j * 8) + (7 - i)) = 0; + count++; + } + } + return count; +} +void print_arraybinary(const uint8_t *b,size_t c){ + int i; + for (i = 0;i < c;i++){ + if (*(b + i) == 0) + printf("0"); + else + printf("1"); + } + printf("\n"); +} diff --git a/client/util.h b/client/util.h index 2d2beaf4..5d9d6cb5 100644 --- a/client/util.h +++ b/client/util.h @@ -65,3 +65,4 @@ void wiegand_add_parity(char *target, char *source, char length); void xor(unsigned char *dst, unsigned char *src, size_t len); int32_t le24toh(uint8_t data[3]); +size_t bytes_to_bits(const uint8_t *src,size_t src_size,uint8_t *des,size_t des_size); \ No newline at end of file diff --git a/common/lfdemod.c b/common/lfdemod.c index f13a567c..d883ed9d 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1482,3 +1482,26 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert) *size = numBits; return errCnt; } +// on successful return 1 otherwise return 0 +int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bits,size_t id_bits_size) +{ + //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future + // otherwise could be a void with no arguments + //set defaults + uint32_t i = 0; + uint32_t lastcheckindex = size - (id_bits_size * 2); + int found = 0; + while (i < lastcheckindex) + { + if (memcmp(BitStream + i,id_bits,id_bits_size) == 0) + { + *startIdx = i; + found = 1; + break; + } + i++; + } + return found; +} + + diff --git a/common/lfdemod.h b/common/lfdemod.h index d16aab9e..3b807b56 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -49,5 +49,6 @@ int IOdemodFSK(uint8_t *dest, size_t size); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int PyramiddemodFSK(uint8_t *dest, size_t *size); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); +int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bit,size_t id_bits_size); #endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index e45bf35e..5fa38ee2 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -96,6 +96,8 @@ typedef struct{ #define CMD_ASK_SIM_TAG 0x021F #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 +#define CMD_VIKING_CLONE_TAG 0x0222 + /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ @@ -135,6 +137,9 @@ typedef struct{ #define CMD_READER_ICLASS_REPLAY 0x0395 #define CMD_ICLASS_ISO14443A_WRITE 0x0397 #define CMD_ICLASS_EML_MEMSET 0x0398 +#define CMD_ICLASS_AUTHENTICATION 0x0399 +#define CMD_ICLASS_READBLOCK 0x039A +#define CMD_ICLASS_CLONE 0x039B // For measurements of the antenna tuning #define CMD_MEASURE_ANTENNA_TUNING 0x0400