ADD: Holimans new changes in master.

This commit is contained in:
iceman1001 2015-01-05 02:01:24 +01:00
commit d3a22c7dfa
23 changed files with 488 additions and 321 deletions

View file

@ -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 // Reader iClass Anticollission
void ReaderIClass(uint8_t arg0) { 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 card_data[24]={0};
uint8_t last_csn[8]={0}; uint8_t last_csn[8]={0};
uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
int read_status= 0; int read_status= 0;
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
bool get_cc = arg0 & FLAG_ICLASS_READER_GET_CC;
setupIclassReader(); setupIclassReader();
size_t datasize = 0; size_t datasize = 0;
while(!BUTTON_PRESS()) while(!BUTTON_PRESS())
{ {
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;
}
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);
//Save that we already sent this....
if(read_status == 2)
memcpy(last_csn, card_data, 8);
LED_B_OFF();
if(abort_after_read) break;
}
}
}
if(traceLen > TRACE_SIZE) { if(traceLen > TRACE_SIZE) {
DbpString("Trace full"); DbpString("Trace full");
break; break;
} }
WDT_HIT();
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)
{
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....
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();
}
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF(); LED_A_OFF();
} }
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
uint8_t act_all[] = { 0x0a };
uint8_t identify[] = { 0x0c }; uint8_t card_data[24]={0};
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint16_t block_crc_LUT[255] = {0};
uint8_t readcheck_cc[]= { 0x88, 0x02 };
{//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 check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
uint16_t crc = 0; uint16_t crc = 0;
uint8_t cardsize=0; uint8_t cardsize=0;
bool read_success=false;
uint8_t mem=0; uint8_t mem=0;
static struct memory_t{ static struct memory_t{
@ -1573,65 +1618,39 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
setupIclassReader(); setupIclassReader();
for(int i=0;i<1;i++) { while(!BUTTON_PRESS()) {
WDT_HIT();
if(traceLen > TRACE_SIZE) { if(traceLen > TRACE_SIZE) {
DbpString("Trace full"); DbpString("Trace full");
break; break;
} }
if (BUTTON_PRESS()) break; uint8_t read_status = handshakeIclassTag(card_data);
if(read_status < 2) continue;
// Send act_all
ReaderTransmitIClass(act_all, 1);
// Card present?
if(ReaderReceiveIClass(resp)) {
ReaderTransmitIClass(identify, 1);
if(ReaderReceiveIClass(resp) == 10) {
// Select card
memcpy(&select[1],resp,8);
ReaderTransmitIClass(select, sizeof(select));
if(ReaderReceiveIClass(resp) == 10) {
Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
resp[0], resp[1], resp[2],
resp[3], resp[4], resp[5],
resp[6], resp[7]);
}
// Card selected
Dbprintf("Readcheck on Sector 2");
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
if(ReaderReceiveIClass(resp) == 8) {
Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x",
resp[0], resp[1], resp[2],
resp[3], resp[4], resp[5],
resp[6], resp[7]);
}else return;
Dbprintf("Authenticate");
//for now replay captured auth (as cc not updated) //for now replay captured auth (as cc not updated)
memcpy(check+5,MAC,4); memcpy(check+5,MAC,4);
//Dbprintf(" AA: %02x %02x %02x %02x",
// check[5], check[6], check[7],check[8]); if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
ReaderTransmitIClass(check, sizeof(check)); {
if(ReaderReceiveIClass(resp) == 4) {
Dbprintf(" AR: %02x %02x %02x %02x",
resp[0], resp[1], resp[2],resp[3]);
}else {
Dbprintf("Error: Authentication Fail!"); Dbprintf("Error: Authentication Fail!");
return; continue;
} }
Dbprintf("Dump Contents");
//first get configuration block //first get configuration block (block 1)
read_success=false; crc = block_crc_LUT[1];
read[1]=1; read[1]=1;
uint8_t *blockno=&read[1];
crc = iclass_crc16((char *)blockno,1);
read[2] = crc >> 8; read[2] = crc >> 8;
read[3] = crc & 0xff; read[3] = crc & 0xff;
while(!read_success){
ReaderTransmitIClass(read, sizeof(read)); if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
if(ReaderReceiveIClass(resp) == 10) { {
read_success=true; Dbprintf("Dump config (block 1) failed");
continue;
}
mem=resp[5]; mem=resp[5];
memory.k16= (mem & 0x80); memory.k16= (mem & 0x80);
memory.book= (mem & 0x20); memory.book= (mem & 0x20);
@ -1639,36 +1658,32 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
memory.lockauth= (mem & 0x2); memory.lockauth= (mem & 0x2);
memory.keyaccess= (mem & 0x1); memory.keyaccess= (mem & 0x1);
} cardsize = memory.k16 ? 255 : 32;
} WDT_HIT();
if (memory.k16){
cardsize=255;
}else cardsize=32;
//then loop around remaining blocks //then loop around remaining blocks
for(uint8_t j=0; j<cardsize; j++){ for(int block=0; block < cardsize; block++){
read_success=false;
uint8_t *blockno=&j; read[1]= block;
//crc_data[0]=j; crc = block_crc_LUT[block];
read[1]=j;
crc = iclass_crc16((char *)blockno,1);
read[2] = crc >> 8; read[2] = crc >> 8;
read[3] = crc & 0xff; read[3] = crc & 0xff;
while(!read_success){
ReaderTransmitIClass(read, sizeof(read)); if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
if(ReaderReceiveIClass(resp) == 10) { {
read_success=true;
Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", 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[3], resp[4], resp[5],
resp[6], resp[7]); resp[6], resp[7]);
}
}
}
}
}
WDT_HIT();
}
}else{
Dbprintf("Failed to dump block %d", block);
}
}
//If we got here, let's break
break;
}
LED_A_OFF(); LED_A_OFF();
} }

View file

@ -586,7 +586,7 @@ static void BuildIdentifyRequest(void);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso15693(void) void AcquireRawAdcSamplesIso15693(void)
{ {
uint8_t *dest = get_bigbufptr_recvrespbuf(); uint8_t *dest = (uint8_t *)BigBuf;
int c = 0; int c = 0;
int getNext = 0; int getNext = 0;
@ -668,7 +668,7 @@ void AcquireRawAdcSamplesIso15693(void)
void RecordRawAdcSamplesIso15693(void) void RecordRawAdcSamplesIso15693(void)
{ {
uint8_t *dest = get_bigbufptr_recvrespbuf(); uint8_t *dest = (uint8_t *)BigBuf;
int c = 0; int c = 0;
int getNext = 0; int getNext = 0;

View file

@ -1879,7 +1879,7 @@ void EM4xLogin(uint32_t Password) {
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { 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; uint16_t bufferlength = 12000;
uint32_t i = 0; uint32_t i = 0;

View file

@ -100,6 +100,7 @@ int Cmdaskdemod(const char *Cmd)
* low for long periods, others just reach the peak and go * low for long periods, others just reach the peak and go
* down) * down)
*/ */
//[marhsmellow] change == to >= for high and <= for low for fuzz
if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) { if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) {
GraphBuffer[i] = 1 - c; GraphBuffer[i] = 1 - c;
} else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){ } else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){

View file

@ -9,7 +9,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <stdio.h> #include <stdio.h>
//#include "proxusb.h" #include <string.h>
#include "proxmark3.h" #include "proxmark3.h"
#include "graph.h" #include "graph.h"
#include "ui.h" #include "ui.h"
@ -34,6 +34,279 @@ int CmdHFTune(const char *Cmd)
SendCommand(&c); SendCommand(&c);
return 0; 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[] = static command_t CommandTable[] =
{ {
@ -49,6 +322,7 @@ static command_t CommandTable[] =
{"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
{"des", CmdHFDES, 0, "{ MIFARE DESfire}"}, {"des", CmdHFDES, 0, "{ MIFARE DESfire}"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -13,5 +13,5 @@
int CmdHF(const char *Cmd); int CmdHF(const char *Cmd);
int CmdHFTune(const char *Cmd); int CmdHFTune(const char *Cmd);
int CmdHFList(const char *Cmd);
#endif #endif

View file

@ -509,7 +509,7 @@ int CmdHF14ASnoop(const char *Cmd) {
if (param_getchar(Cmd, 0) == 'h') { if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("It get data from the field and saves it into command buffer."); 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("Usage: hf 14a snoop [c][r]");
PrintAndLog("c - triggered by first data from card"); PrintAndLog("c - triggered by first data from card");
PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)"); 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[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"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"}, {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"}, {"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
{"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"}, {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},

View file

@ -26,7 +26,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
//#include "proxusb.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "data.h" #include "data.h"
#include "graph.h" #include "graph.h"

View file

@ -41,152 +41,45 @@ int xorbits_8(uint8_t val)
return res & 1; return res & 1;
} }
#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
void explain(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;
}
int CmdHFiClassList(const char *Cmd) int CmdHFiClassList(const char *Cmd)
{ {
bool ShowWaitCycles = false; PrintAndLog("Deprecated command, use 'hf list iclass' instead");
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;
}
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;
}
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]);
}
}
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";
}
}
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));
}
}
}
return 0; return 0;
} }
@ -321,7 +214,11 @@ int CmdHFiClassReader(const char *Cmd)
uint8_t * data = resp.d.asBytes; uint8_t * data = resp.d.asBytes;
PrintAndLog("isOk:%02x", isOK); PrintAndLog("isOk:%02x", isOK);
if( isOK == 0){
//Aborted
PrintAndLog("Quitting...");
return 0;
}
if(isOK > 0) if(isOK > 0)
{ {
PrintAndLog("CSN: %s",sprint_hex(data,8)); PrintAndLog("CSN: %s",sprint_hex(data,8));
@ -424,7 +321,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
UsbCommand c = {CMD_READER_ICLASS, {0}}; 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) if(!fake_dummy_test)
SendCommand(&c); SendCommand(&c);
@ -577,13 +474,10 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"list", CmdHFiClassList, 0, "List iClass history"}, {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
{"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
{"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
{"reader",CmdHFiClassReader, 0, "Read an 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"}, {"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
{"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},

View file

@ -1223,9 +1223,6 @@ int CmdHF14AMfELoad(const char *Cmd)
return 1; return 1;
} }
// for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
// for(blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
blockNum = 0; blockNum = 0;
while(!feof(f)){ while(!feof(f)){
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
@ -1243,6 +1240,7 @@ int CmdHF14AMfELoad(const char *Cmd)
if(strlen(buf) && feof(f)) if(strlen(buf) && feof(f))
break; break;
PrintAndLog("File content error. Block data must include 32 HEX symbols"); PrintAndLog("File content error. Block data must include 32 HEX symbols");
fclose(f);
return 2; return 2;
} }
@ -1252,6 +1250,7 @@ int CmdHF14AMfELoad(const char *Cmd)
if (mfEmlSetMem(buf8, blockNum, 1)) { if (mfEmlSetMem(buf8, blockNum, 1)) {
PrintAndLog("Cant set emul block: %3d", blockNum); PrintAndLog("Cant set emul block: %3d", blockNum);
fclose(f);
return 3; return 3;
} }
blockNum++; blockNum++;
@ -1262,7 +1261,6 @@ int CmdHF14AMfELoad(const char *Cmd)
if ((blockNum != numBlocks)) { if ((blockNum != numBlocks)) {
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks); PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
fclose(f);
return 4; return 4;
} }
PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename); PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename);

View file

@ -139,9 +139,7 @@ int CmdIndalaDemod(const char *Cmd)
uint8_t rawbits[4096]; uint8_t rawbits[4096];
int rawbit = 0; int rawbit = 0;
int worst = 0, worstPos = 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) { for (i = 0; i < GraphTraceLen-1; i += 2) {
count += 1; count += 1;
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {

View file

@ -26,7 +26,6 @@
#define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits = #define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits =
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdReadBlk(const char *Cmd) int CmdReadBlk(const char *Cmd)
{ {
int block = -1; int block = -1;

View file

@ -30,13 +30,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 "cipher.h"
#include "cipherutils.h" #include "cipherutils.h"
#include <stdio.h> #include <stdio.h>

View file

@ -30,13 +30,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 #ifndef CIPHER_H
#define CIPHER_H #define CIPHER_H
#include <stdint.h> #include <stdint.h>

View file

@ -30,10 +30,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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> #include <stdint.h>

View file

@ -30,13 +30,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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 #ifndef CIPHERUTILS_H
#define CIPHERUTILS_H #define CIPHERUTILS_H
#include <stdint.h> #include <stdint.h>

View file

@ -79,6 +79,7 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
FILE *fh=fopen(fileName,"wb"); FILE *fh=fopen(fileName,"wb");
if(!fh) { if(!fh) {
PrintAndLog("Failed to write to file '%s'", fileName); PrintAndLog("Failed to write to file '%s'", fileName);
free(fh);
return 1; return 1;
} }
fwrite(data, 1, datalen, fh); fwrite(data, 1, datalen, fh);
@ -94,10 +95,12 @@ int loadFile(const char *fileName, void* data, size_t datalen)
FILE *filehandle = fopen(fileName, "rb"); FILE *filehandle = fopen(fileName, "rb");
if(!filehandle) { if(!filehandle) {
PrintAndLog("Failed to read from file '%s'", fileName); PrintAndLog("Failed to read from file '%s'", fileName);
free(filehandle);
return 1; return 1;
} }
fread(data,datalen,1,filehandle); fread(data,datalen,1,filehandle);
fclose(filehandle); fclose(filehandle);
free(filehandle);
return 0; return 0;
} }
/** /**

View file

@ -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 * 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 * 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 *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 * @param fmt
*/ */
void prnlog(char *fmt, ...); void prnlog(char *fmt, ...);

View file

@ -18,6 +18,10 @@
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass". * 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 * Copyright (C) 2014 Martin Holst Swende
* *
* This is free software: you can redistribute it and/or modify * This is free software: you can redistribute it and/or modify
@ -30,12 +34,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * 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/>.
*
*
*
****************************************************************************/ ****************************************************************************/
/** /**
@ -403,7 +403,7 @@ void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8])
//Calculate HASH0(DES)) //Calculate HASH0(DES))
uint64_t crypt_csn = x_bytes_to_num(crypted_csn, 8); 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); hash0(crypt_csn,div_key);
} }

View file

@ -47,7 +47,6 @@ void SendCommand(UsbCommand *c) {
PrintAndLog("Sending bytes to proxmark failed - offline"); PrintAndLog("Sending bytes to proxmark failed - offline");
return; return;
} }
/** /**
The while-loop below causes hangups at times, when the pm3 unit is unresponsive 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. or disconnected. The main console thread is alive, but comm thread just spins here.

View file

@ -66,11 +66,11 @@ char* Iso15693sprintUID(char *target,uint8_t *uid) {
return target; 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 char i;
unsigned int data; unsigned int data;
unsigned int crc = 0xffff; uint16_t crc = 0xffff;
if (length == 0) if (length == 0)
return (~crc); return (~crc);

View file

@ -621,8 +621,8 @@ int IOdemodFSK(uint8_t *dest, size_t size)
testMax = dest[idx]; testMax = dest[idx];
} }
//if not just noise //if not, just noise
if (testMax < 170) return -2; if (testMax < 20) return -2;
// FSK demodulator // FSK demodulator
size = fskdemod(dest, size, 64, 1, 10, 8); // RF/64 and invert size = fskdemod(dest, size, 64, 1, 10, 8); // RF/64 and invert

View file

@ -188,6 +188,7 @@ typedef struct {
//Iclass reader flags //Iclass reader flags
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 #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: // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the common_area is present */ /* Whether a bootloader that understands the common_area is present */