}
+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{
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);
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<cardsize; j++){
- read_success=false;
- uint8_t *blockno=&j;
- //crc_data[0]=j;
- read[1]=j;
- crc = iclass_crc16((char *)blockno,1);
+ for(int block=0; block < cardsize; block++){
+
+ read[1]= block;
+ crc = block_crc_LUT[block];
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(" %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();
}
//-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso15693(void)
{
- uint8_t *dest = get_bigbufptr_recvrespbuf();
+ uint8_t *dest = (uint8_t *)BigBuf;
int c = 0;
int getNext = 0;
void RecordRawAdcSamplesIso15693(void)
{
- uint8_t *dest = get_bigbufptr_recvrespbuf();
+ uint8_t *dest = (uint8_t *)BigBuf;
int c = 0;
int getNext = 0;
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;
* 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))){
//-----------------------------------------------------------------------------
#include <stdio.h>
-//#include "proxusb.h"
+#include <string.h>
#include "proxmark3.h"
#include "graph.h"
#include "ui.h"
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[] =
{
{"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}
};
int CmdHF(const char *Cmd);
int CmdHFTune(const char *Cmd);
-
+int CmdHFList(const char *Cmd);
#endif
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,...)");
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, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
{"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
-//#include "proxusb.h"
+
#include "proxmark3.h"
#include "data.h"
#include "graph.h"
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;
}
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));
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);
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"},
return 1;\r
}\r
\r
-// for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {\r
-// for(blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
- \r
blockNum = 0;\r
while(!feof(f)){\r
memset(buf, 0, sizeof(buf));\r
if(strlen(buf) && feof(f))\r
break;\r
PrintAndLog("File content error. Block data must include 32 HEX symbols");\r
+ fclose(f);\r
return 2;\r
}\r
\r
\r
if (mfEmlSetMem(buf8, blockNum, 1)) {\r
PrintAndLog("Cant set emul block: %3d", blockNum);\r
+ fclose(f);\r
return 3;\r
}\r
blockNum++;\r
\r
if ((blockNum != numBlocks)) {\r
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);\r
- fclose(f);\r
return 4;\r
}\r
PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename);\r
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)) {
#define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits = \r
static int CmdHelp(const char *Cmd);\r
\r
-\r
int CmdReadBlk(const char *Cmd)\r
{\r
int block = -1;\r
* 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 <http://www.gnu.org/licenses/>.
- *
- *
- *
+ * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
-
#include "cipher.h"
#include "cipherutils.h"
#include <stdio.h>
* 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 <http://www.gnu.org/licenses/>.
- *
- *
- *
+ * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
-
#ifndef CIPHER_H
#define CIPHER_H
#include <stdint.h>
* 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 <http://www.gnu.org/licenses/>.
- *
- *
- *
+ * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <stdint.h>
* 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 <http://www.gnu.org/licenses/>.
- *
- *
- *
+ * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
-
#ifndef CIPHERUTILS_H
#define CIPHERUTILS_H
#include <stdint.h>
FILE *fh=fopen(fileName,"wb");
if(!fh) {
PrintAndLog("Failed to write to file '%s'", fileName);
+ free(fh);
return 1;
}
fwrite(data, 1, datalen, fh);
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;
}
/**
* 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, ...);
* 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
* 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 <http://www.gnu.org/licenses/>.
- *
- *
- *
+ * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
-
/**
//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);
}
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.
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);
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
//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 */