Implemented client side changes for iclass hack, attempted to fix issues with trace. The trace functionality from iso14443 has been rewritten, unfortunately iclass used that also, which made iclass 'list' stop functioning, both for simulation and snooping

This commit is contained in:
Martin Holst Swende 2014-04-24 14:13:33 +02:00
parent ff7bb4ef17
commit 17cba2693d
4 changed files with 230 additions and 71 deletions

View file

@ -146,7 +146,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param);
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data); void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
void ReaderIso14443a(UsbCommand * c); void ReaderIso14443a(UsbCommand * c);
// Also used in iclass.c // Also used in iclass.c
bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t iSamples, uint32_t dwParity, bool bReader); bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t iSamples, uint32_t dwParity, bool readerToTag);
uint32_t GetParity(const uint8_t * pbtCmd, int iLen); uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);
void iso14a_clear_trace(); void iso14a_clear_trace();

View file

@ -666,12 +666,7 @@ static RAMFUNC int ManchesterDecoding(int v)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void RAMFUNC SnoopIClass(void) 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; // 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 // a good trigger condition to get started is probably when we see a
@ -681,13 +676,9 @@ void RAMFUNC SnoopIClass(void)
// The command (reader -> tag) that we're receiving. // The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes. // The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough! // 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. // 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 // reset traceLen to 0
iso14a_set_tracing(TRUE); iso14a_set_tracing(TRUE);
@ -709,7 +700,7 @@ void RAMFUNC SnoopIClass(void)
memset(trace, 0x44, RECV_CMD_OFFSET); memset(trace, 0x44, RECV_CMD_OFFSET);
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
Demod.output = receivedResponse; Demod.output = tagToReaderResponse;
Demod.len = 0; Demod.len = 0;
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
@ -721,7 +712,7 @@ void RAMFUNC SnoopIClass(void)
// And the reader -> tag commands // And the reader -> tag commands
memset(&Uart, 0, sizeof(Uart)); memset(&Uart, 0, sizeof(Uart));
Uart.output = receivedCmd; Uart.output = readerToTagCmd;
Uart.byteCntMax = 32; // was 100 (greg)//////////////////////////////////////////////////////////////////////// Uart.byteCntMax = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
@ -764,20 +755,13 @@ void RAMFUNC SnoopIClass(void)
//samples += 4; //samples += 4;
samples += 1; 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) { if(smpl & 0xF) {
decbyte ^= (1 << (3 - div)); decbyte ^= (1 << (3 - div));
} }
//decbyte ^= (MajorityNibble[(smpl & 0x0F)] << (3 - div));
// FOR READER SIDE COMMUMICATION... // FOR READER SIDE COMMUMICATION...
//decbyte ^= ((smpl & 0x10) << (3 - div));
decbyter <<= 2; decbyter <<= 2;
decbyter ^= (smpl & 0x30); decbyter ^= (smpl & 0x30);
@ -788,20 +772,10 @@ void RAMFUNC SnoopIClass(void)
if(OutOfNDecoding((smpl & 0xF0) >> 4)) { if(OutOfNDecoding((smpl & 0xF0) >> 4)) {
rsamples = samples - Uart.samples; rsamples = samples - Uart.samples;
LED_C_ON(); LED_C_ON();
//if(triggered) {
trace[traceLen++] = ((rsamples >> 0) & 0xff); if(!LogTrace(readerToTagCmd,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
trace[traceLen++] = ((rsamples >> 8) & 0xff); //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
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. */ /* And ready to receive another command. */
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
/* And also reset the demod code, which might have been */ /* And also reset the demod code, which might have been */
@ -819,26 +793,13 @@ void RAMFUNC SnoopIClass(void)
rsamples = samples - Demod.samples; rsamples = samples - Demod.samples;
LED_B_ON(); LED_B_ON();
// timestamp, as a count of samples if(!LogTrace(tagToReaderResponse,Demod.len, rsamples, Demod.parityBits,FALSE)) break;
trace[traceLen++] = ((rsamples >> 0) & 0xff); //if (!LogTrace(NULL, 0, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, 0, FALSE)) break;
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;
// And ready to receive another response. // And ready to receive another response.
memset(&Demod, 0, sizeof(Demod)); memset(&Demod, 0, sizeof(Demod));
Demod.output = receivedResponse; Demod.output = tagToReaderResponse;
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
LED_C_OFF(); LED_C_OFF();
} }
@ -1019,6 +980,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
} }
else if(simType == 2) 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 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 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. // in order to obtain the keys, as in the "dismantling iclass"-paper.
@ -1131,13 +1093,13 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived)
} }
// Okay, look at the command now. // Okay, look at the command now.
if(receivedCmd[0] == 0x0a) { if(receivedCmd[0] == 0x0a || receivedCmd[0] == 0x26) {
// Reader in anticollission phase // Reader in anticollission phase
resp = resp1; respLen = resp1Len; //order = 1; resp = resp1; respLen = resp1Len; //order = 1;
respdata = &sof; respdata = &sof;
respsize = sizeof(sof); respsize = sizeof(sof);
//resp = resp2; respLen = resp2Len; order = 2; //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) { } else if(receivedCmd[0] == 0x0c) {
// Reader asks for anticollission CSN // Reader asks for anticollission CSN
resp = resp2; respLen = resp2Len; //order = 2; resp = resp2; respLen = resp2Len; //order = 2;
@ -1180,6 +1142,7 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived)
respdata = NULL; respdata = NULL;
respsize = 0; respsize = 0;
} else { } else {
//#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
// Never seen this command before // Never seen this command before
Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x", Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x",
len, len,
@ -1205,14 +1168,21 @@ void doIClassSimulation(uint8_t csn[], int breakAfterMacReceived)
} }
if (tracing) { if (tracing) {
LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE); //LogTrace(receivedCmd,len, rsamples, Uart.parityBits, TRUE);
if (respdata != NULL) { if(!LogTrace(receivedCmd,len, rsamples, Uart.parityBits,TRUE))
LogTrace(respdata,respsize, rsamples, SwapBits(GetParity(respdata,respsize),respsize), FALSE); {
}
if(traceLen > TRACE_SIZE) {
DbpString("Trace full"); DbpString("Trace full");
break; 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); memset(receivedCmd, 0x44, RECV_CMD_SIZE);
} }

View file

@ -190,7 +190,7 @@ void AppendCrc14443a(uint8_t* data, int len)
} }
// The function LogTrace() is also used by the iClass implementation in iClass.c // The function LogTrace() is also used by the iClass implementation in iClass.c
bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp, uint32_t dwParity, bool bReader) bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp, uint32_t dwParity, bool readerToTag)
{ {
// Return when trace is full // Return when trace is full
if (traceLen + sizeof(timestamp) + sizeof(dwParity) + iLen >= TRACE_SIZE) { if (traceLen + sizeof(timestamp) + sizeof(dwParity) + iLen >= TRACE_SIZE) {
@ -203,7 +203,8 @@ bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t timestamp,
trace[traceLen++] = ((timestamp >> 8) & 0xff); trace[traceLen++] = ((timestamp >> 8) & 0xff);
trace[traceLen++] = ((timestamp >> 16) & 0xff); trace[traceLen++] = ((timestamp >> 16) & 0xff);
trace[traceLen++] = ((timestamp >> 24) & 0xff); trace[traceLen++] = ((timestamp >> 24) & 0xff);
if (!bReader) {
if (!readerToTag) {
trace[traceLen - 1] |= 0x80; trace[traceLen - 1] |= 0x80;
} }
trace[traceLen++] = ((dwParity >> 0) & 0xff); trace[traceLen++] = ((dwParity >> 0) & 0xff);

View file

@ -21,10 +21,139 @@
#include "cmdhficlass.h" #include "cmdhficlass.h"
#include "common.h" #include "common.h"
#include "util.h" #include "util.h"
#include "cmdmain.h"
static int CmdHelp(const char *Cmd); 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) 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]; uint8_t got[1920];
GetFromBigBuf(got,sizeof(got),0); GetFromBigBuf(got,sizeof(got),0);
@ -50,7 +179,9 @@ int CmdHFiClassList(const char *Cmd)
isResponse = 0; isResponse = 0;
} }
int metric = 0; int metric = 0;
int parityBits = *((uint32_t *)(got+i+4)); int parityBits = *((uint32_t *)(got+i+4));
// 4 bytes of additional information... // 4 bytes of additional information...
// maximum of 32 additional parity bit information // maximum of 32 additional parity bit information
@ -177,21 +308,78 @@ int CmdHFiClassSim(const char *Cmd)
uint8_t simType = 0; uint8_t simType = 0;
uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
if (strlen(Cmd)<2) { if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf iclass sim <sim type> <CSN (16 hex symbols)>"); 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 0 031FEC8AF7FF12E0");
PrintAndLog(" sample: hf iclass sim 2");
return 0; return 0;
} }
simType = param_get8(Cmd, 0); simType = param_get8(Cmd, 0);
if(simType == 0)
{
if (param_gethex(Cmd, 1, CSN, 16)) { if (param_gethex(Cmd, 1, CSN, 16)) {
PrintAndLog("A CSN should consist of 16 HEX symbols"); PrintAndLog("A CSN should consist of 16 HEX symbols");
return 1; return 1;
} }
PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8)); PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType}}; }
if(simType > 2)
{
PrintAndLog("Undefined simptype %d", simType);
return 1;
}
uint8_t numberOfCSNs=0;
UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
memcpy(c.d.asBytes, CSN, 8); 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); SendCommand(&c);
/*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500); /*UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 1500);