From d3a22c7dfa87bf5e21d228849a602194be4a0895 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Jan 2015 02:01:24 +0100 Subject: [PATCH] ADD: Holimans new changes in master. --- armsrc/iclass.c | 261 +++++++++++++++++--------------- armsrc/iso15693.c | 4 +- armsrc/lfops.c | 2 +- client/cmddata.c | 1 + client/cmdhf.c | 280 ++++++++++++++++++++++++++++++++++- client/cmdhf.h | 2 +- client/cmdhf14a.c | 4 +- client/cmdhf15.c | 2 +- client/cmdhficlass.c | 186 +++++------------------ client/cmdhfmf.c | 6 +- client/cmdlf.c | 4 +- client/cmdlft55xx.c | 1 - client/loclass/cipher.c | 6 +- client/loclass/cipher.h | 6 +- client/loclass/cipherutils.c | 5 +- client/loclass/cipherutils.h | 6 +- client/loclass/fileutils.c | 3 + client/loclass/fileutils.h | 2 +- client/loclass/ikeys.c | 12 +- client/proxmark3.c | 1 - common/iso15693tools.c | 4 +- common/lfdemod.c | 4 +- include/usb_cmd.h | 1 + 23 files changed, 485 insertions(+), 318 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 74705b49..cf1931fd 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1467,97 +1467,142 @@ void setupIclassReader() } +size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries) +{ + while(retries-- > 0) + { + ReaderTransmitIClass(command, cmdsize); + if(expected_size == ReaderReceiveIClass(resp)){ + return 0; + } + } + return 1;//Error +} + +/** + * @brief Talks to an iclass tag, sends the commands to get CSN and CC. + * @param card_data where the CSN and CC are stored for return + * @return 0 = fail + * 1 = Got CSN + * 2 = Got CSN and CC + */ +uint8_t handshakeIclassTag(uint8_t *card_data) +{ + static uint8_t act_all[] = { 0x0a }; + static uint8_t identify[] = { 0x0c }; + static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static uint8_t readcheck_cc[]= { 0x88, 0x02 }; + uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); + + uint8_t read_status = 0; + + // Send act_all + ReaderTransmitIClass(act_all, 1); + // Card present? + if(!ReaderReceiveIClass(resp)) return read_status;//Fail + //Send Identify + ReaderTransmitIClass(identify, 1); + //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC + uint8_t len = ReaderReceiveIClass(resp); + if(len != 10) return read_status;//Fail + + //Copy the Anti-collision CSN to our select-packet + memcpy(&select[1],resp,8); + //Select the card + ReaderTransmitIClass(select, sizeof(select)); + //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC + len = ReaderReceiveIClass(resp); + if(len != 10) return read_status;//Fail + + //Success - level 1, we got CSN + //Save CSN in response data + memcpy(card_data,resp,8); + + //Flag that we got to at least stage 1, read CSN + read_status = 1; + + // Card selected, now read e-purse (cc) + ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); + if(ReaderReceiveIClass(resp) == 8) { + //Save CC (e-purse) in response data + memcpy(card_data+8,resp,8); + + //Got both + read_status = 2; + } + + return read_status; +} + // Reader iClass Anticollission void ReaderIClass(uint8_t arg0) { - 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 card_data[24]={0}; uint8_t last_csn[8]={0}; - uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); - int read_status= 0; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; + bool get_cc = arg0 & FLAG_ICLASS_READER_GET_CC; setupIclassReader(); size_t datasize = 0; while(!BUTTON_PRESS()) { + + if(traceLen > TRACE_SIZE) { + DbpString("Trace full"); + break; + } WDT_HIT(); - // Send act_all - ReaderTransmitIClass(act_all, 1); - // Card present? - if(ReaderReceiveIClass(resp)) { - - ReaderTransmitIClass(identify, 1); - - if(ReaderReceiveIClass(resp) == 10) { - //Copy the Anti-collision CSN to our select-packet - memcpy(&select[1],resp,8); - //Dbprintf("Anti-collision 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]); - //Select the card - ReaderTransmitIClass(select, sizeof(select)); - - if(ReaderReceiveIClass(resp) == 10) { - //Save CSN in response data - memcpy(card_data,resp,8); - datasize += 8; - //Flag that we got to at least stage 1, read CSN - read_status = 1; - - // Card selected - //Dbprintf("Readcheck on Sector 2"); - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - if(ReaderReceiveIClass(resp) == 8) { - //Save CC (e-purse) in response data - memcpy(card_data+8,resp,8); - datasize += 8; - //Got both - read_status = 2; - } + read_status = handshakeIclassTag(card_data); + + if(read_status == 0) continue; + if(read_status == 1) datasize = 8; + if(read_status == 2) datasize = 16; LED_B_ON(); //Send back to client, but don't bother if we already sent this if(memcmp(last_csn, card_data, 8) != 0) - cmd_send(CMD_ACK,read_status,0,0,card_data,datasize); + { + if(!get_cc || (get_cc && read_status == 2)) + { + cmd_send(CMD_ACK,read_status,0,0,card_data,datasize); + if(abort_after_read) { + LED_A_OFF(); + return; + } //Save that we already sent this.... - if(read_status == 2) memcpy(last_csn, card_data, 8); - + } + //If 'get_cc' was specified and we didn't get a CC, we'll just keep trying... + } LED_B_OFF(); - - if(abort_after_read) break; - } - } - } - - if(traceLen > TRACE_SIZE) { - DbpString("Trace full"); - break; - } } + cmd_send(CMD_ACK,0,0,0,card_data, 0); LED_A_OFF(); } void ReaderIClass_Replay(uint8_t arg0, 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 card_data[24]={0}; + uint16_t block_crc_LUT[255] = {0}; + + {//Generate a lookup table for block crc + for(int block = 0; block < 255; block++){ + char bl = block; + block_crc_LUT[block] = iclass_crc16(&bl ,1); + } + } + //Dbprintf("Lookup table: %02x %02x %02x" ,block_crc_LUT[0],block_crc_LUT[1],block_crc_LUT[2]); + uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; uint16_t crc = 0; uint8_t cardsize=0; - bool read_success=false; uint8_t mem=0; static struct memory_t{ @@ -1573,65 +1618,39 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { setupIclassReader(); - for(int i=0;i<1;i++) { + while(!BUTTON_PRESS()) { + + WDT_HIT(); 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)); + uint8_t read_status = handshakeIclassTag(card_data); + if(read_status < 2) continue; - 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 { + + if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5)) + { Dbprintf("Error: Authentication Fail!"); - return; + continue; } - Dbprintf("Dump Contents"); - //first get configuration block - read_success=false; + + //first get configuration block (block 1) + crc = block_crc_LUT[1]; 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; + + if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10)) + { + Dbprintf("Dump config (block 1) failed"); + continue; + } + mem=resp[5]; memory.k16= (mem & 0x80); memory.book= (mem & 0x20); @@ -1639,36 +1658,32 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { memory.lockauth= (mem & 0x2); memory.keyaccess= (mem & 0x1); - } - } - if (memory.k16){ - cardsize=255; - }else cardsize=32; + cardsize = memory.k16 ? 255 : 32; + WDT_HIT(); + //then loop around remaining blocks - for(uint8_t j=0; j> 8; read[3] = crc & 0xff; - while(!read_success){ - ReaderTransmitIClass(read, sizeof(read)); - if(ReaderReceiveIClass(resp) == 10) { - read_success=true; + + if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10)) + { Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", - j, resp[0], resp[1], resp[2], + block, resp[0], resp[1], resp[2], resp[3], resp[4], resp[5], resp[6], resp[7]); - } - } - } + + }else{ + Dbprintf("Failed to dump block %d", block); + } } - WDT_HIT(); + //If we got here, let's break + break; } - LED_A_OFF(); } diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 4a767b56..c4f5f612 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -586,7 +586,7 @@ static void BuildIdentifyRequest(void); //----------------------------------------------------------------------------- void AcquireRawAdcSamplesIso15693(void) { - uint8_t *dest = get_bigbufptr_recvrespbuf(); + uint8_t *dest = (uint8_t *)BigBuf; int c = 0; int getNext = 0; @@ -668,7 +668,7 @@ void AcquireRawAdcSamplesIso15693(void) void RecordRawAdcSamplesIso15693(void) { - uint8_t *dest = get_bigbufptr_recvrespbuf(); + uint8_t *dest = (uint8_t *)BigBuf; int c = 0; int getNext = 0; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index cc9814be..08bae44d 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1879,7 +1879,7 @@ void EM4xLogin(uint32_t Password) { void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { - uint8_t *dest = get_bigbufptr_recvrespbuf(); + uint8_t *dest = (uint8_t *)BigBuf; uint16_t bufferlength = 12000; uint32_t i = 0; diff --git a/client/cmddata.c b/client/cmddata.c index 8d74750d..9a19dca7 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -100,6 +100,7 @@ int Cmdaskdemod(const char *Cmd) * low for long periods, others just reach the peak and go * down) */ + //[marhsmellow] change == to >= for high and <= for low for fuzz if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) { GraphBuffer[i] = 1 - c; } else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){ diff --git a/client/cmdhf.c b/client/cmdhf.c index dda0a669..0ed3f013 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -9,7 +9,7 @@ //----------------------------------------------------------------------------- #include -//#include "proxusb.h" +#include #include "proxmark3.h" #include "graph.h" #include "ui.h" @@ -34,6 +34,279 @@ int CmdHFTune(const char *Cmd) SendCommand(&c); return 0; } +// for the time being. Need better Bigbuf handling. +#define TRACE_SIZE 3000 + +#define ICLASS_CMD_ACTALL 0x0A +#define ICLASS_CMD_IDENTIFY 0x0C +#define ICLASS_CMD_READ 0x0C +#define ICLASS_CMD_SELECT 0x81 +#define ICLASS_CMD_PAGESEL 0x84 +#define ICLASS_CMD_READCHECK 0x88 +#define ICLASS_CMD_CHECK 0x05 +#define ICLASS_CMD_SOF 0x0F +#define ICLASS_CMD_HALT 0x00 + +#define iso14443_CMD_WUPA 0x52 +#define iso14443_CMD_SELECT 0x93 +#define iso14443_CMD_SELECT_2 0x95 +#define iso14443_CMD_REQ 0x26 +#define iso14443_CMD_READBLOCK 0x30 +#define iso14443_CMD_WRITEBLOCK 0xA0 +#define iso14443_CMD_INC 0xC0 +#define iso14443_CMD_DEC 0xC1 +#define iso14443_CMD_RESTORE 0xC2 +#define iso14443_CMD_TRANSFER 0xB0 +#define iso14443_CMD_HALT 0x50 +#define iso14443_CMD_RATS 0xE0 + + +void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]) + { + case iso14443_CMD_WUPA: snprintf(exp,size,"WUPA"); break; + case iso14443_CMD_SELECT:{ + if(cmdsize > 2) + { + snprintf(exp,size,"SELECT_UID"); break; + }else + { + snprintf(exp,size,"SELECT_ALL"); break; + } + } + case iso14443_CMD_SELECT_2: snprintf(exp,size,"SELECT_2"); break; + case iso14443_CMD_REQ: snprintf(exp,size,"REW"); break; + case iso14443_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; + case iso14443_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; + case iso14443_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; + case iso14443_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; + case iso14443_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; + case iso14443_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; + case iso14443_CMD_HALT: snprintf(exp,size,"HALT"); break; + case iso14443_CMD_RATS: snprintf(exp,size,"RATS"); break; + default: snprintf(exp,size,"?"); break; + } + return; +} + +void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + + if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ) + { + snprintf(exp,size,"READ(%d)",cmd[1]); + return; + } + + switch(cmd[0]) + { + case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break; + case ICLASS_CMD_IDENTIFY: snprintf(exp,size,"IDENTIFY"); break; + case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break; + case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break; + case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break; + case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break; + case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break; + case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break; + default: snprintf(exp,size,"?"); break; + } + return; +} + + + +uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, bool iclass, bool showWaitCycles) +{ + bool isResponse; + uint16_t duration, data_len,parity_len; + + uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp; + char explanation[30] = {0}; + + first_timestamp = *((uint32_t *)(trace)); + timestamp = *((uint32_t *)(trace + tracepos)); + // Break and stick with current result if buffer was not completely full + if (timestamp == 0x44444444) return TRACE_SIZE; + + tracepos += 4; + duration = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; + isResponse = true; + } else { + isResponse = false; + } + parity_len = (data_len-1)/8 + 1; + + if (tracepos + data_len + parity_len >= TRACE_SIZE) { + return TRACE_SIZE; + } + + uint8_t *frame = trace + tracepos; + tracepos += data_len; + uint8_t *parityBytes = trace + tracepos; + tracepos += parity_len; + + //--- Draw the data column + char line[16][110]; + for (int j = 0; j < data_len; j++) { + int oddparity = 0x01; + int k; + + for (k=0 ; k<8 ; k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); + } + + uint8_t parityBits = parityBytes[j>>3]; + + if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]); + } else { + sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]); + } + } + //--- Draw the CRC column + bool crcError = false; + + if (data_len > 2) { + uint8_t b1, b2; + if(iclass) + { + if(!isResponse && data_len == 4 ) { + // Rough guess that this is a command from the reader + // For iClass the command byte is not part of the CRC + ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2); + } + else { + // For other data.. CRC might not be applicable (UPDATE commands etc.) + ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2); + } + + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + crcError = true; + } + + }else{//Iso 14443a + + ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); + + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + if(!(isResponse & (data_len < 6))) + { + crcError = true; + } + } + } + + } + char *crc = crcError ? "!crc" :" "; + + EndOfTransmissionTimestamp = timestamp + duration; + + if(!isResponse) + { + if(iclass) annotateIclass(explanation,sizeof(explanation),frame,data_len); + else annotateIso14443a(explanation,sizeof(explanation),frame,data_len); + } + + int num_lines = (data_len - 1)/16 + 1; + for (int j = 0; j < num_lines; j++) { + if (j == 0) { + PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s", + (timestamp - first_timestamp), + (EndOfTransmissionTimestamp - first_timestamp), + (isResponse ? "Tag" : "Rdr"), + line[j], + (j == num_lines-1) ? crc : " ", + (j == num_lines-1) ? explanation : ""); + } else { + PrintAndLog(" | | | %-64s| %s| %s", + line[j], + (j == num_lines-1)?crc:" ", + (j == num_lines-1) ? explanation : ""); + } + } + + bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; + + if (showWaitCycles && !isResponse && next_isResponse) { + uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); + if (next_timestamp != 0x44444444) { + PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + (EndOfTransmissionTimestamp - first_timestamp), + (next_timestamp - first_timestamp), + " ", + (next_timestamp - EndOfTransmissionTimestamp)); + } + } + return tracepos; +} + +int CmdHFList(const char *Cmd) +{ + bool showWaitCycles = false; + char type[40] = {0}; + int tlen = param_getstr(Cmd,0,type); + char param = param_getchar(Cmd, 1); + bool errors = false; + bool iclass = false; + //Validate params + if(tlen == 0 || (strcmp(type, "iclass") != 0 && strcmp(type,"14a") != 0)) + { + errors = true; + } + if(param == 'h' || (param !=0 && param != 'f')) + { + errors = true; + } + + if (errors) { + PrintAndLog("List protocol data in trace buffer."); + PrintAndLog("Usage: hf list [14a|iclass] [f]"); + PrintAndLog(" 14a - interpret data as iso14443a communications"); + PrintAndLog(" iclass - interpret data as iclass communications"); + PrintAndLog(" f - show frame delay times as well"); + PrintAndLog(""); + PrintAndLog("example: hf list 14a f"); + PrintAndLog("example: hf list iclass"); + return 0; + } + if(strcmp(type, "iclass") == 0) + { + iclass = true; + } + + if (param == 'f') { + showWaitCycles = true; + } + + + uint8_t trace[TRACE_SIZE]; + uint16_t tracepos = 0; + GetFromBigBuf(trace, TRACE_SIZE, 0); + WaitForResponse(CMD_ACK, NULL); + + PrintAndLog("Recorded Activity"); + PrintAndLog(""); + PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); + PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); + PrintAndLog("iClass - Timings are not as accurate"); + PrintAndLog(""); + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); + PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|"); + + while(tracepos < TRACE_SIZE) + { + tracepos = printTraceLine(tracepos, trace, iclass, showWaitCycles); + } + return 0; +} + static command_t CommandTable[] = { @@ -45,10 +318,11 @@ static command_t CommandTable[] = {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, {"des", CmdHFDES, 0, "{ MIFARE DESfire}"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, + {"list", CmdHFList, 1, "List protocol data in trace buffer"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhf.h b/client/cmdhf.h index ff20a950..026357b5 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -13,5 +13,5 @@ int CmdHF(const char *Cmd); int CmdHFTune(const char *Cmd); - +int CmdHFList(const char *Cmd); #endif diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 5798fee6..62d95b4b 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -509,7 +509,7 @@ int CmdHF14ASnoop(const char *Cmd) { if (param_getchar(Cmd, 0) == 'h') { PrintAndLog("It get data from the field and saves it into command buffer."); - PrintAndLog("Buffer accessible from command hf 14a list."); + PrintAndLog("Buffer accessible from command hf list 14a."); PrintAndLog("Usage: hf 14a snoop [c][r]"); PrintAndLog("c - triggered by first data from card"); PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)"); @@ -694,7 +694,7 @@ static void waitCmd(uint8_t iSelect) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdHF14AList, 0, "List ISO 14443a history"}, + {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443a history"}, {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"}, {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443 Type A UIDs in one go"}, {"sim", CmdHF14ASim, 0, " -- Fake ISO 14443a tag"}, diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 76e1ea9c..25ae2a82 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -26,7 +26,7 @@ #include #include #include -//#include "proxusb.h" + #include "proxmark3.h" #include "data.h" #include "graph.h" diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 75c6e2c9..38713220 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -41,152 +41,45 @@ int xorbits_8(uint8_t val) return res & 1; } -int CmdHFiClassList(const char *Cmd) -{ - bool ShowWaitCycles = false; - char param = param_getchar(Cmd, 0); - - if (param != 0) { - PrintAndLog("List data in trace buffer."); - PrintAndLog("Usage: hf iclass list"); - PrintAndLog("h - help"); - PrintAndLog("sample: hf iclass list"); - return 0; - } - -// for the time being. Need better Bigbuf handling. -#define TRACE_SIZE 3000 - - uint8_t trace[TRACE_SIZE]; - GetFromBigBuf(trace, TRACE_SIZE, 0); - WaitForResponse(CMD_ACK,NULL); - - PrintAndLog("Recorded Activity"); - PrintAndLog(""); - PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); - PrintAndLog("All times are in carrier periods (1/13.56Mhz)"); - PrintAndLog(""); - PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC "); - PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------"); - - uint16_t tracepos = 0; - uint16_t duration; - uint16_t data_len; - uint16_t parity_len; - bool isResponse; - uint32_t timestamp; - uint32_t first_timestamp; - uint32_t EndOfTransmissionTimestamp; - - for (;;) { - - if(tracepos >= TRACE_SIZE) { - break; - } +#define ICLASS_CMD_ACTALL 0x0A +#define ICLASS_CMD_IDENTIFY 0x0C +#define ICLASS_CMD_READ 0x0C - timestamp = *((uint32_t *)(trace + tracepos)); - if(tracepos == 0) { - first_timestamp = timestamp; - } - - // Break and stick with current result if buffer was not completely full - if (timestamp == 0x44444444) break; - - tracepos += 4; - duration = *((uint16_t *)(trace + tracepos)); - tracepos += 2; - data_len = *((uint16_t *)(trace + tracepos)); - tracepos += 2; - - if (data_len & 0x8000) { - data_len &= 0x7fff; - isResponse = true; - } else { - isResponse = false; - } +#define ICLASS_CMD_SELECT 0x81 +#define ICLASS_CMD_PAGESEL 0x84 +#define ICLASS_CMD_READCHECK 0x88 +#define ICLASS_CMD_CHECK 0x05 +#define ICLASS_CMD_SOF 0x0F +#define ICLASS_CMD_HALT 0x00 - parity_len = (data_len-1)/8 + 1; - if (tracepos + data_len + parity_len >= TRACE_SIZE) { - break; - } - - uint8_t *frame = trace + tracepos; - tracepos += data_len; - uint8_t *parityBytes = trace + tracepos; - tracepos += parity_len; - - char line[16][110]; - for (int j = 0; j < data_len; j++) { - int oddparity = 0x01; - int k; - - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } - - uint8_t parityBits = parityBytes[j>>3]; - if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { - sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]); - } else { - sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]); - } - - } +void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ - char *crc = ""; - if (data_len > 2) { - uint8_t b1, b2; - if(!isResponse && data_len == 4 ) { - // Rough guess that this is a command from the reader - // For iClass the command byte is not part of the CRC - ComputeCrc14443(CRC_ICLASS, &frame[1], data_len-3, &b1, &b2); - if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { - crc = "!crc"; - } + if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ) + { + snprintf(exp,size,"READ(%d)",cmd[1]); + return; } - else { - // For other data.. CRC might not be applicable (UPDATE commands etc.) - ComputeCrc14443(CRC_ICLASS, frame, data_len-2, &b1, &b2); - if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { - crc = "!crc"; - } - } - } - EndOfTransmissionTimestamp = timestamp + duration; - - int num_lines = (data_len - 1)/16 + 1; - for (int j = 0; j < num_lines; j++) { - if (j == 0) { - PrintAndLog(" %9d | %9d | %s | %-64s| %s", - (timestamp - first_timestamp), - (EndOfTransmissionTimestamp - first_timestamp), - (isResponse ? "Tag" : "Rdr"), - line[j], - (j == num_lines-1)?crc:""); - } else { - PrintAndLog(" | | | %-64s| %s", - line[j], - (j == num_lines-1)?crc:""); - } - } - - bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; - - if (ShowWaitCycles && !isResponse && next_isResponse) { - uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); - if (next_timestamp != 0x44444444) { - PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", - (EndOfTransmissionTimestamp - first_timestamp), - (next_timestamp - first_timestamp), - " ", - (next_timestamp - EndOfTransmissionTimestamp)); - } - } - - } - + switch(cmd[0]) + { + case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break; + case ICLASS_CMD_IDENTIFY: snprintf(exp,size,"IDENTIFY"); break; + case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break; + case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break; + case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break; + case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break; + case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break; + case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break; + default: snprintf(exp,size,"?"); break; + } + return; +} + +int CmdHFiClassList(const char *Cmd) +{ + PrintAndLog("Deprecated command, use 'hf list iclass' instead"); return 0; } @@ -321,7 +214,11 @@ int CmdHFiClassReader(const char *Cmd) uint8_t * data = resp.d.asBytes; PrintAndLog("isOk:%02x", isOK); - + if( isOK == 0){ + //Aborted + PrintAndLog("Quitting..."); + return 0; + } if(isOK > 0) { PrintAndLog("CSN: %s",sprint_hex(data,8)); @@ -424,7 +321,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) UsbCommand c = {CMD_READER_ICLASS, {0}}; - c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE; + c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC; if(!fake_dummy_test) SendCommand(&c); @@ -577,13 +474,10 @@ int CmdHFiClass_iso14443A_write(const char *Cmd) static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFiClassList, 0, "List iClass history"}, + {"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"}, {"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"}, diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index f32ae444..49928c9a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1223,9 +1223,6 @@ int CmdHF14AMfELoad(const char *Cmd) return 1; } -// for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { -// for(blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - blockNum = 0; while(!feof(f)){ memset(buf, 0, sizeof(buf)); @@ -1243,6 +1240,7 @@ int CmdHF14AMfELoad(const char *Cmd) if(strlen(buf) && feof(f)) break; PrintAndLog("File content error. Block data must include 32 HEX symbols"); + fclose(f); return 2; } @@ -1252,6 +1250,7 @@ int CmdHF14AMfELoad(const char *Cmd) if (mfEmlSetMem(buf8, blockNum, 1)) { PrintAndLog("Cant set emul block: %3d", blockNum); + fclose(f); return 3; } blockNum++; @@ -1262,7 +1261,6 @@ int CmdHF14AMfELoad(const char *Cmd) if ((blockNum != numBlocks)) { PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks); - fclose(f); return 4; } PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename); diff --git a/client/cmdlf.c b/client/cmdlf.c index 9a9984d1..e38eee51 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -139,9 +139,7 @@ int CmdIndalaDemod(const char *Cmd) uint8_t rawbits[4096]; int rawbit = 0; int worst = 0, worstPos = 0; - - PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); - + // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); for (i = 0; i < GraphTraceLen-1; i += 2) { count += 1; if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 6f1ada7c..24685eb9 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -26,7 +26,6 @@ #define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits = static int CmdHelp(const char *Cmd); - int CmdReadBlk(const char *Cmd) { int block = -1; diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 9c1c2cfd..1c9dae8b 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -30,13 +30,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - * + * along with IClassCipher. If not, see . ****************************************************************************/ - #include "cipher.h" #include "cipherutils.h" #include diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index 176a2976..314a560a 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -30,13 +30,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - * + * along with IClassCipher. If not, see . ****************************************************************************/ - #ifndef CIPHER_H #define CIPHER_H #include diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index f9c62273..f82a11ce 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -30,10 +30,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - * + * along with IClassCipher. If not, see . ****************************************************************************/ #include diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index cb090f69..e2338534 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -30,13 +30,9 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - * + * along with IClassCipher. If not, see . ****************************************************************************/ - #ifndef CIPHERUTILS_H #define CIPHERUTILS_H #include diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 74c36a4d..443070c1 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -79,6 +79,7 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si FILE *fh=fopen(fileName,"wb"); if(!fh) { PrintAndLog("Failed to write to file '%s'", fileName); + free(fh); return 1; } fwrite(data, 1, datalen, fh); @@ -94,10 +95,12 @@ int loadFile(const char *fileName, void* data, size_t datalen) FILE *filehandle = fopen(fileName, "rb"); if(!filehandle) { PrintAndLog("Failed to read from file '%s'", fileName); + free(filehandle); return 1; } fread(data,datalen,1,filehandle); fclose(filehandle); + free(filehandle); return 0; } /** diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 02cfcef9..405c9704 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -64,7 +64,7 @@ int loadFile(const char *fileName, void* data, size_t datalen); * Utility function to print to console. This is used consistently within the library instead * of printf, but it actually only calls printf. The reason to have this method is to *make it simple to plug this library into proxmark, which has this function already to - * write also to a logfile. When doing so, just delete this function. + * write also to a logfile. When doing so, just point this function to use PrintAndLog * @param fmt */ void prnlog(char *fmt, ...); diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 4c5bba2b..fccd71d8 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -18,6 +18,10 @@ * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and * Milosch Meriac in the paper "Dismantling IClass". * + * This is a reference implementation of iclass key diversification. I'm sure it can be + * optimized heavily. It is written for ease of understanding and correctness, please take it + * and tweak it and make a super fast version instead, using this for testing and verification. + * Copyright (C) 2014 Martin Holst Swende * * This is free software: you can redistribute it and/or modify @@ -30,12 +34,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - * + * along with IClassCipher. If not, see . ****************************************************************************/ - /** @@ -403,7 +403,7 @@ void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8]) //Calculate HASH0(DES)) uint64_t crypt_csn = x_bytes_to_num(crypted_csn, 8); - uint64_t crypted_csn_swapped = swapZvalues(crypt_csn); + //uint64_t crypted_csn_swapped = swapZvalues(crypt_csn); hash0(crypt_csn,div_key); } diff --git a/client/proxmark3.c b/client/proxmark3.c index 66571144..4b463f1d 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -47,7 +47,6 @@ void SendCommand(UsbCommand *c) { PrintAndLog("Sending bytes to proxmark failed - offline"); return; } - /** The while-loop below causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, but comm thread just spins here. diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 964059ce..0ec5492b 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -66,11 +66,11 @@ char* Iso15693sprintUID(char *target,uint8_t *uid) { return target; } -unsigned short iclass_crc16(char *data_p, unsigned short length) +uint16_t iclass_crc16(char *data_p, unsigned short length) { unsigned char i; unsigned int data; - unsigned int crc = 0xffff; + uint16_t crc = 0xffff; if (length == 0) return (~crc); diff --git a/common/lfdemod.c b/common/lfdemod.c index 873b6305..eb5a4d95 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -621,8 +621,8 @@ int IOdemodFSK(uint8_t *dest, size_t size) testMax = dest[idx]; } - //if not just noise - if (testMax < 170) return -2; + //if not, just noise + if (testMax < 20) return -2; // FSK demodulator size = fskdemod(dest, size, 64, 1, 10, 8); // RF/64 and invert diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 111f7ec7..ecdf8ac1 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -188,6 +188,7 @@ typedef struct { //Iclass reader flags #define FLAG_ICLASS_READER_ONLY_ONCE 0x01 +#define FLAG_ICLASS_READER_GET_CC 0x02 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: /* Whether a bootloader that understands the common_area is present */ -- 2.39.2