//-----------------------------------------------------------------------------
void RAMFUNC SnoopIClass(void)
{
-// DEFINED ABOVE
-// #define RECV_CMD_OFFSET 3032
-// #define RECV_RES_OFFSET 3096
-// #define DMA_BUFFER_OFFSET 3160
-// #define DMA_BUFFER_SIZE 4096
-// #define TRACE_SIZE 3000
+
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough!
- uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+ uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
// The response (tag -> reader) that we're receiving.
- uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
+ uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
- // As we receive stuff, we copy it from receivedCmd or receivedResponse
- // into trace, along with its length and other annotations.
- //uint8_t *trace = (uint8_t *)BigBuf;
-
// reset traceLen to 0
iso14a_set_tracing(TRUE);
iso14a_clear_trace();
memset(trace, 0x44, RECV_CMD_OFFSET);
// Set up the demodulator for tag -> reader responses.
- Demod.output = receivedResponse;
+ Demod.output = tagToReaderResponse;
Demod.len = 0;
Demod.state = DEMOD_UNSYNCD;
// And the reader -> tag commands
memset(&Uart, 0, sizeof(Uart));
- Uart.output = receivedCmd;
+ Uart.output = readerToTagCmd;
Uart.byteCntMax = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
Uart.state = STATE_UNSYNCD;
//samples += 4;
samples += 1;
- //div2++;
- //if(div2 > 3) {
- //div2 = 0;
- //decbyte ^= ((smpl & 0x01) << (3 - div));
- //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1)) << (3 - div)); // better already...
- //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1) | ((smpl & 0x04) >> 2)) << (3 - div)); // even better...
if(smpl & 0xF) {
decbyte ^= (1 << (3 - div));
}
- //decbyte ^= (MajorityNibble[(smpl & 0x0F)] << (3 - div));
// FOR READER SIDE COMMUMICATION...
- //decbyte ^= ((smpl & 0x10) << (3 - div));
+
decbyter <<= 2;
decbyter ^= (smpl & 0x30);
if(OutOfNDecoding((smpl & 0xF0) >> 4)) {
rsamples = samples - Uart.samples;
LED_C_ON();
- //if(triggered) {
- trace[traceLen++] = ((rsamples >> 0) & 0xff);
- trace[traceLen++] = ((rsamples >> 8) & 0xff);
- trace[traceLen++] = ((rsamples >> 16) & 0xff);
- trace[traceLen++] = ((rsamples >> 24) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 0) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 8) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff);
- trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff);
- trace[traceLen++] = Uart.byteCnt;
- memcpy(trace+traceLen, receivedCmd, Uart.byteCnt);
- traceLen += Uart.byteCnt;
- if(traceLen > TRACE_SIZE) break;
- //}
- /* And ready to receive another command. */
+
+ if(!LogTrace(readerToTagCmd,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
+ //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
+
+ /* And ready to receive another command. */
Uart.state = STATE_UNSYNCD;
/* And also reset the demod code, which might have been */
/* false-triggered by the commands from the reader. */
rsamples = samples - Demod.samples;
LED_B_ON();
- // timestamp, as a count of samples
- trace[traceLen++] = ((rsamples >> 0) & 0xff);
- trace[traceLen++] = ((rsamples >> 8) & 0xff);
- trace[traceLen++] = ((rsamples >> 16) & 0xff);
- trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 0) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 8) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);
- trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);
- // length
- trace[traceLen++] = Demod.len;
- memcpy(trace+traceLen, receivedResponse, Demod.len);
- traceLen += Demod.len;
- if(traceLen > TRACE_SIZE) break;
-
- //triggered = TRUE;
+ if(!LogTrace(tagToReaderResponse,Demod.len, rsamples, Demod.parityBits,FALSE)) break;
+ //if (!LogTrace(NULL, 0, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, 0, FALSE)) break;
+
// And ready to receive another response.
memset(&Demod, 0, sizeof(Demod));
- Demod.output = receivedResponse;
+ Demod.output = tagToReaderResponse;
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
}
else if(simType == 2)
{
+ Dbprintf("Going into attack mode");
// In this mode, a number of csns are within datain. We'll simulate each one, one at a time
// in order to collect MAC's from the reader. This can later be used in an offlne-attack
// in order to obtain the keys, as in the "dismantling iclass"-paper.
}
// Okay, look at the command now.
- if(receivedCmd[0] == 0x0a) {
+ if(receivedCmd[0] == 0x0a || receivedCmd[0] == 0x26) {
// Reader in anticollission phase
resp = resp1; respLen = resp1Len; //order = 1;
respdata = &sof;
respsize = sizeof(sof);
//resp = resp2; respLen = resp2Len; order = 2;
- //DbpString("Hello request from reader:");
+ Dbprintf("Hello request from reader, %02x, tracing=%d", receivedCmd[0], tracing);
} else if(receivedCmd[0] == 0x0c) {
// Reader asks for anticollission CSN
resp = resp2; respLen = resp2Len; //order = 2;
respdata = NULL;
respsize = 0;
} else {
+ //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
// Never seen this command before
Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x",
len,
}
if (tracing) {
- LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE);
- if (respdata != NULL) {
- LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
- }
- if(traceLen > TRACE_SIZE) {
+ //LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE);
+ if(!LogTrace(receivedCmd,len, rsamples, Uart.parityBits,TRUE))
+ {
DbpString("Trace full");
break;
}
+
+ if (respdata != NULL) {
+ //LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE);
+ if(!LogTrace(respdata,respsize, rsamples,SwapBits(GetParity(respdata,respsize),respsize),FALSE))
+ {
+ DbpString("Trace full");
+ break;
+ }
+ }
}
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
}
#include "cmdhficlass.h"
#include "common.h"
#include "util.h"
+#include "cmdmain.h"
static int CmdHelp(const char *Cmd);
+int xorbits_8(uint8_t val)
+{
+ uint8_t res = val ^ (val >> 1); //1st pass
+ res = res ^ (res >> 1); // 2nd pass
+ res = res ^ (res >> 2); // 3rd pass
+ res = res ^ (res >> 4); // 4th pass
+ 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;
+ }
+
+ uint8_t got[1920];
+ GetFromBigBuf(got,sizeof(got),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");
+ PrintAndLog("-----------|-----------|-----|--------");
+
+ int i;
+ uint32_t first_timestamp = 0;
+ uint32_t timestamp;
+ bool tagToReader;
+ uint32_t parityBits;
+ uint8_t len;
+ uint8_t *frame;
+ uint32_t EndOfTransmissionTimestamp = 0;
+
+ uint8_t empty[4] = {0x44,0x44,0x44,0x44};
+
+ for( i=0; i < 1900;)
+ {
+ //First 32 bits contain
+ // isResponse (1 bit)
+ // timestamp (remaining)
+ //Then paritybits
+ //Then length
+ timestamp = *((uint32_t *)(got+i));
+ parityBits = *((uint32_t *)(got+i+4));
+ len = got[i+8];
+ frame = (got+i+9);
+ uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff;
+
+ tagToReader = timestamp & 0x80000000;
+ timestamp &= 0x7fffffff;
+
+ if(i==0) {
+ first_timestamp = timestamp;
+ }
+
+ // Break and stick with current result if buffer
+ // was not completely full
+ if(memcmp(frame,empty,sizeof(empty))) break;
+
+ char line[1000] = "";
+
+ if(len)//We have some data to display
+ {
+ int j,oddparity;
+
+ for(j = 0; j < len ; j++)
+ {
+ oddparity = 0x01 ^ xorbits_8(frame[j] & 0xFF);
+
+ if (tagToReader && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
+ sprintf(line+(j*4), "%02x! ", frame[j]);
+ } else {
+ sprintf(line+(j*4), "%02x ", frame[j]);
+ }
+ }
+ }else
+ {
+ if (ShowWaitCycles) {
+ sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp));
+ }
+ }
+
+ char *crc = "";
+
+ if(len > 2)
+ {
+ uint8_t b1, b2;
+ if(!tagToReader && 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], len-3, &b1, &b2);
+ }
+ else {
+ // For other data.. CRC might not be applicable (UPDATE commands etc.)
+ ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
+ }
+
+ if (b1 != frame[len-2] || b2 != frame[len-1]) {
+ crc = (tagToReader & (len < 8)) ? "" : " !crc";
+ }
+ }
+
+ i += (len + 9);
+ EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff;
+
+ // Not implemented for iclass on the ARM-side
+ //if (!ShowWaitCycles) i += 9;
+
+ PrintAndLog(" %9d | %9d | %s | %s %s",
+ (timestamp - first_timestamp),
+ (EndOfTransmissionTimestamp - first_timestamp),
+ (len?(tagToReader ? "Tag" : "Rdr"):" "),
+ line, crc);
+ }
+ return 0;
+}
+
+int CmdHFiClassListOld(const char *Cmd)
{
uint8_t got[1920];
GetFromBigBuf(got,sizeof(got),0);
isResponse = 0;
}
+
int metric = 0;
+
int parityBits = *((uint32_t *)(got+i+4));
// 4 bytes of additional information...
// maximum of 32 additional parity bit information
uint8_t simType = 0;
uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- if (strlen(Cmd)<2) {
- PrintAndLog("Usage: hf iclass sim <sim type> <CSN (16 hex symbols)>");
+ if (strlen(Cmd)<1) {
+ PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
+ PrintAndLog(" options");
+ PrintAndLog(" 0 <CSN> simulate the given CSN");
+ PrintAndLog(" 1 simulate default CSN");
+ PrintAndLog(" 2 iterate CSNs, gather MACs");
PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
+ PrintAndLog(" sample: hf iclass sim 2");
return 0;
}
simType = param_get8(Cmd, 0);
- if (param_gethex(Cmd, 1, CSN, 16)) {
- PrintAndLog("A CSN should consist of 16 HEX symbols");
- return 1;
+
+ if(simType == 0)
+ {
+ if (param_gethex(Cmd, 1, CSN, 16)) {
+ PrintAndLog("A CSN should consist of 16 HEX symbols");
+ return 1;
+ }
+ PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
+
}
- PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
+ if(simType > 2)
+ {
+ PrintAndLog("Undefined simptype %d", simType);
+ return 1;
+ }
+ uint8_t numberOfCSNs=0;
- UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType}};
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
memcpy(c.d.asBytes, CSN, 8);
+
+ if(simType == 2)
+ {
+ c.arg[1] = 10;//10 CSNs
+ uint8_t csns[] ={
+ /* Order Simulated CSN HASH1 Recovered key bytes */
+ /* 1 */ 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0,// 0101000045014545 00,01 45
+ /* 2 */ 0x03,0x0B,0x0E,0xFE,0xF7,0xFF,0x12,0xE0,// 0202000045014545 02
+ /* 3 */ 0x04,0x0D,0x0D,0xFD,0xF7,0xFF,0x12,0xE0,// 0303000045014545 03
+ /* 4 */ 0x04,0x0F,0x0F,0xF7,0xF7,0xFF,0x12,0xE0,// 0901000045014545 09
+ /* 5 */ 0x01,0x13,0x10,0xF4,0xF7,0xFF,0x12,0xE0,// 0C00000045014545 0C
+ /* 6 */ 0x02,0x14,0x10,0xF2,0xF7,0xFF,0x12,0xE0,// 0E00000045014545 0E
+ /* 7 */ 0x05,0x17,0x10,0xEC,0xF7,0xFF,0x12,0xE0,// 1400000045014545 14
+ /* 8 */ 0x00,0x6B,0x6F,0xDF,0xF7,0xFF,0x12,0xE0,// 2121000045014545 21
+ /* 9 */ 0x03,0x6B,0x6E,0xDE,0xF7,0xFF,0x12,0xE0,// 2222000045014545 22
+ /* 10 */ 0x04,0x6D,0x6D,0xDD,0xF7,0xFF,0x12,0xE0,// 2323000045014545 23
+ /* 11 */ 0x00,0x4F,0x4B,0x43,0xF7,0xFF,0x12,0xE0,// 3D45000045014545 3D
+ /* 12 */ 0x00,0x4B,0x4F,0x3F,0xF7,0xFF,0x12,0xE0,// 4141000045014545 41
+ /* 13 */ 0x03,0x4B,0x4E,0x3E,0xF7,0xFF,0x12,0xE0,// 4242000045014545 42
+ /* 14 */ 0x04,0x4D,0x4D,0x3D,0xF7,0xFF,0x12,0xE0,// 4343000045014545 43
+ /* 15 */ 0x04,0x37,0x37,0x7F,0xF7,0xFF,0x12,0xE0,// 0159000045014545 59
+ /* 16 */ 0x00,0x2B,0x2F,0x9F,0xF7,0xFF,0x12,0xE0,// 6161000045014545 61
+ /* 17 */ 0x03,0x2B,0x2E,0x9E,0xF7,0xFF,0x12,0xE0,// 6262000045014545 62
+ /* 18 */ 0x04,0x2D,0x2D,0x9D,0xF7,0xFF,0x12,0xE0,// 6363000045014545 63
+ /* 19 */ 0x00,0x27,0x23,0xBB,0xF7,0xFF,0x12,0xE0,// 456D000045014545 6D
+ /* 20 */ 0x02,0x52,0xAA,0x80,0xF7,0xFF,0x12,0xE0,// 0066000045014545 66
+ /* 21 */ 0x00,0x5C,0xA6,0x80,0xF7,0xFF,0x12,0xE0,// 006A000045014545 6A
+ /* 22 */ 0x01,0x5F,0xA4,0x80,0xF7,0xFF,0x12,0xE0,// 006C000045014545 6C
+ /* 23 */ 0x06,0x5E,0xA2,0x80,0xF7,0xFF,0x12,0xE0,// 006E000045014545 6E
+ /* 24 */ 0x02,0x0E,0x0E,0xFC,0xF7,0xFF,0x12,0xE0,// 0402000045014545 04
+ /* 25 */ 0x05,0x0D,0x0E,0xFA,0xF7,0xFF,0x12,0xE0,// 0602000045014545 06
+ /* 26 */ 0x06,0x0F,0x0D,0xF9,0xF7,0xFF,0x12,0xE0,// 0703000045014545 07
+ /* 27 */ 0x00,0x01,0x05,0x1D,0xF7,0xFF,0x12,0xE0,// 630B000045014545 0B
+ /* 28 */ 0x02,0x07,0x01,0x1D,0xF7,0xFF,0x12,0xE0,// 630F000045014545 0F
+ /* 29 */ 0x04,0x7F,0x7F,0xA7,0xF7,0xFF,0x12,0xE0,// 5911000045014545 11
+ /* 30 */ 0x04,0x60,0x6E,0xE8,0xF7,0xFF,0x12,0xE0,// 1822000045014545 18
+ };
+ memcpy(c.d.asBytes, csns, sizeof(c.d.asBytes));
+
+ }
+
SendCommand(&c);
/*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);