lf viking and iclass

add lf viking
add Iclass write
This commit is contained in:
Gusto the bun 2015-07-19 01:07:27 +10:00
commit 7f99524209
20 changed files with 970 additions and 400 deletions

View file

@ -683,7 +683,12 @@ void UsbPacketReceived(uint8_t *packet, int len)
break; break;
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1); CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
break; break;
case CMD_VIKING_CLONE_TAG:
CopyViKingtoT55x7(c->arg[0],c->arg[1]);
break;
#endif #endif
#ifdef WITH_HITAG #ifdef WITH_HITAG
@ -865,9 +870,19 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_READER_ICLASS_REPLAY: case CMD_READER_ICLASS_REPLAY:
ReaderIClass_Replay(c->arg[0], c->d.asBytes); ReaderIClass_Replay(c->arg[0], c->d.asBytes);
break; break;
case CMD_ICLASS_EML_MEMSET: case CMD_ICLASS_EML_MEMSET:
emlSet(c->d.asBytes,c->arg[0], c->arg[1]); emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
break; break;
case CMD_ICLASS_ISO14443A_WRITE:
IClass_iso14443A_write(c->arg[0],c->d.asBytes);
break;
case CMD_ICLASS_AUTHENTICATION:
IClass_Authentication(c->d.asBytes);
break;
case CMD_ICLASS_CLONE:
IClass_Clone(c->arg[0],c->arg[1],c->d.asBytes);
break;
#endif #endif
case CMD_BUFF_CLEAR: case CMD_BUFF_CLEAR:

View file

@ -168,7 +168,10 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
void ReaderIClass(uint8_t arg0); void ReaderIClass(uint8_t arg0);
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
void IClass_iso14443A_GetPublic(uint8_t arg0); void IClass_iso14443A_GetPublic(uint8_t arg0);
void IClass_Authentication(uint8_t *MAC);
void IClass_iso14443A_write(uint8_t blockno,uint8_t *data);
void IClass_Clone(uint8_t startblock,uint8_t endblock,uint8_t *data);
void CopyViKingtoT55x7(uint32_t block1,uint32_t block2);
// hitag2.h // hitag2.h
void SnoopHitag(uint32_t type); void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);

View file

@ -1903,131 +1903,57 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
LED_A_OFF(); LED_A_OFF();
} }
void IClass_Authentication(uint8_t *MAC){
//2. Create Read method (cut-down from above) based off responses from 1. uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Since we have the MAC could continue to use replay function. uint8_t resp[ICLASS_BUFFER_SIZE];
//3. Create Write method memcpy(check+5,MAC,4);
/*
void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) { sendCmdGetResponseWithRetries(check, sizeof(check),resp, 8, 5);
uint8_t act_all[] = { 0x0a }; // successful
uint8_t identify[] = { 0x0c }; }
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void IClass_iso14443A_write(uint8_t blockNo, uint8_t *data) {
uint8_t readcheck_cc[]= { 0x88, 0x02 }; uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 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 }; write[1] = blockNo;
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(write + 2,data,8); // data
memcpy(write+10,data + 8,4); // mac no
uint16_t crc = 0; uint8_t r[12];
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // 0x87
sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5);
// Reset trace buffer Dbprintf("reply [%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]",r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9],r[10],r[11]);
memset(trace, 0x44, RECV_CMD_OFFSET);
traceLen = 0; if (memcmp(data,r,8) == 0)
Dbprintf("Write block [%02x] ok",blockNo);
// Setup SSC else
FpgaSetupSsc(); Dbprintf("Write block [%02x] fail",blockNo);
// Start from off (no field generated) }
// Signal field is off with the appropriate LED void IClass_Clone(uint8_t startblock,uint8_t endblock,uint8_t *data){
LED_D_OFF(); uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); uint8_t r[12];
SpinDelay(200); int i;
int written = 0;
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); int total_block = (endblock - startblock) + 1;
for (i = 0; i < total_block;i++){
// Now give it time to spin up. // block number
// Signal field is on with the appropriate LED write[0] = 0x87;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); write[1] = i + startblock;
SpinDelay(200); // data
memcpy(write + 2,data + (i * 12),8);
LED_A_ON(); // mac number
memcpy(write + 10,data + ((i * 12) + 8), 4);
for(int i=0;i<1;i++) { sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5);
if(traceLen > TRACE_SIZE) { if (memcmp(write + 2,r,8) == 0){
DbpString("Trace full"); Dbprintf("Write block [%02x] ok",i + 6);
break; written++;
} }
else
if (BUTTON_PRESS()) break; Dbprintf("Write block [%02x] fail",i + 6);
}
// Send act_all if (written == total_block)
ReaderTransmitIClass(act_all, 1); Dbprintf("Clone complete");
// Card present? else
if(ReaderReceiveIClass(resp)) { Dbprintf("Clone incomplete");
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)
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 {
Dbprintf("Error: Authentication Fail!");
return;
}
Dbprintf("Write Block");
//read configuration for max block number
read_success=false;
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;
mem=resp[5];
memory.k16= (mem & 0x80);
memory.book= (mem & 0x20);
memory.k2= (mem & 0x8);
memory.lockauth= (mem & 0x2);
memory.keyaccess= (mem & 0x1);
}
}
if (memory.k16){
cardsize=255;
}else cardsize=32;
//check card_size
memcpy(write+1,blockNo,1);
memcpy(write+2,data,8);
memcpy(write+10,mac,4);
while(!send_success){
ReaderTransmitIClass(write, sizeof(write));
if(ReaderReceiveIClass(resp) == 10) {
write_success=true;
}
}//
}
WDT_HIT();
}
LED_A_OFF();
}*/

View file

@ -2062,3 +2062,14 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF(); LED_D_OFF();
} }
void CopyViKingtoT55x7(uint32_t block1,uint32_t block2)
{
LED_D_ON();
T55xxWriteBlock(block1,1,0,0);
T55xxWriteBlock(block2,2,0,0);
T55xxWriteBlock(T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 2 << T5555_MAXBLOCK_SHIFT,0,0,1);
LED_D_OFF();
DbpString("DONE!");
}

1
client/.history Normal file
View file

@ -0,0 +1 @@
lf

View file

@ -93,6 +93,7 @@ CMDSRCS = nonce2key/crapto1.c\
cmdlfem4x.c \ cmdlfem4x.c \
cmdlfhitag.c \ cmdlfhitag.c \
cmdlfti.c \ cmdlfti.c \
cmdlfviking.c\
cmdparser.c \ cmdparser.c \
cmdmain.c \ cmdmain.c \
cmdlft55xx.c \ cmdlft55xx.c \
@ -104,7 +105,7 @@ CMDSRCS = nonce2key/crapto1.c\
aes.c\ aes.c\
protocols.c\ protocols.c\
sha1.c\ sha1.c\
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
#-DDEBUG -Dverbose=1 #-DDEBUG -Dverbose=1

View file

@ -1870,6 +1870,53 @@ int CmdRawDemod(const char *Cmd)
return ans; return ans;
} }
int AmVikingDecode(const uint8_t *id){
// searching the buffer for the id
uint8_t id_bits[32];
// convert 4 bytes of id to 32 bits present in 32 bytes data;
bytes_to_bits(id,4,id_bits,sizeof(id_bits));
printf("binary : ");
print_arraybinary(id_bits,sizeof(id_bits));
printf("\n");
size_t idx = 0;
size_t BitLen = DemodBufferLen;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
memcpy(BitStream, DemodBuffer, BitLen);
if (VikingDecode(BitStream,BitLen,&idx,id_bits,sizeof(id_bits)) == 1)
{
setDemodBuf(BitStream,64, idx);
printf("Found Viking tag\n");
CmdPrintDemodBuff("x");
}
else
{
printf("Not found Viking tag\n");
}
return 0;
}
int AMVikingDemod(const uint8_t *id){
// demod am clock 32 fail
if (!ASKDemod("32",g_debugMode,false,1))
return 0;
// search for the card id from bitstream.
return AmVikingDecode(id);
}
//by Gusto
// takes 1 argument <8 bytes of Hex number on the card
// print binary found and saves in grapbuffer for further commands
int CmdAMVikingDemod(const char *Cmd){
uint8_t id[4];
if (param_gethex(Cmd,0,id,8) == 1)
{
PrintAndLog("Usage: data vikingdemod CardID 8 bytes of hex number");
return 0;
}
printf("Card ID : %02X%02X%02X%02X\n",id[0],id[1],id[2],id[3]);
// try to demod AMViking
return AMVikingDemod(id);
}
int CmdGrid(const char *Cmd) int CmdGrid(const char *Cmd)
{ {
sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
@ -2279,6 +2326,7 @@ static command_t CommandTable[] =
{"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"}, {"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
{"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"}, {"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
{"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"}, {"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"},
{"vikingdemod", CmdAMVikingDemod, 1, "Demodulate a Viking AM tag from GraphBuffer"},
//{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"}, //{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"},
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"}, {"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"},
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"}, {"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"},

View file

@ -67,7 +67,8 @@ int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose); int NRZrawDemod(const char *Cmd, bool verbose);
void printEM410x(uint32_t hi, uint64_t id); void printEM410x(uint32_t hi, uint64_t id);
int getSamples(const char *Cmd, bool silent); int getSamples(const char *Cmd, bool silent);
int AMVikingDemod(const uint8_t *cardid);
int CmdAMVikingDemod(const char *cmd);
#define MAX_DEMOD_BUF_LEN (1024*128) #define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];

933
client/cmdhficlass.c Normal file → Executable file
View file

@ -31,9 +31,14 @@
#include "loclass/fileutils.h" #include "loclass/fileutils.h"
#include "protocols.h" #include "protocols.h"
#include "usb_cmd.h" #include "usb_cmd.h"
typedef struct iclass_block {
uint8_t d[8];
} iclass_block_t;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static uint8_t GLOBAL_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static uint8_t HS_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static uint8_t BLANK_KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static bool HS_KEY_LOAD = false;
int xorbits_8(uint8_t val) int xorbits_8(uint8_t val)
{ {
uint8_t res = val ^ (val >> 1); //1st pass uint8_t res = val ^ (val >> 1); //1st pass
@ -42,7 +47,117 @@ int xorbits_8(uint8_t val)
res = res ^ (res >> 4); // 4th pass res = res ^ (res >> 4); // 4th pass
return res & 1; return res & 1;
} }
void CmdHFiClass_printkey(const char* keyname,const uint8_t *key){
printf("%s : %02X%02X%02X%02X%02X%02X%02X%02X\n",keyname,key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7]);
}
int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
{
FILE *f = fopen(filename, "rb");
if(!f) {
PrintAndLog("Failed to read from file '%s'", filename);
return 1;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
size_t bytes_read = fread(buffer, 1, len, f);
fclose(f);
if(fsize != len)
{
PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
return 1;
}
if(bytes_read != len)
{
PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
return 1;
}
return 0;
}
int usage_iclass_readkeyfile(){
printf("usage: hf iclass readkeyfile <filename>\n");
return 0;
}
int CmdHFiClassReadKeyFile(const char *Cmd){
uint8_t key[8];
if ( (strlen(Cmd) < 1) || (readKeyfile(Cmd,sizeof(key),key) != 0)) {
return usage_iclass_readkeyfile();
}
CmdHFiClass_printkey("Key ",key);
return 0;
}
int usage_iclass_savekeyfile(){
printf("usage: hf iclass writekeyfile <KEY> filename\n");
return 0;
}
int CmdHFiClassSaveKeyFile(const char *Cmd){
char filename[50];
uint8_t key[8];
FILE *file;
if (param_gethex(Cmd, 0, key, 16))
{
PrintAndLog("KEY must include 16 HEX symbols");
return 1;
}
if (param_getstr(Cmd,1,filename) < 1)
return usage_iclass_savekeyfile();
file = fopen(filename,"wb");
if (file == NULL) {
printf("error opening file %s\n",filename);
return 0;
}
if (fwrite(&key,sizeof(key),1,file))
printf("write key to file was successful\n");
else
printf("write key to file was fail\n");
fclose(file);
return 0;
}
int CmdHFiClass_SendAuthentication(uint8_t *MAC){
UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
memcpy(d.d.asBytes,MAC, 4);
SendCommand(&d);
return 0;
}
int CmdHFiClass_SendACK(uint8_t *CSN,uint8_t *CCNR) {
UsbCommand resp;
UsbCommand c = {CMD_READER_ICLASS, {0}};
c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
{
PrintAndLog("Command execute timeout");
return 1;
}
uint8_t isOK = resp.arg[0] & 0xff;
uint8_t * data = resp.d.asBytes;
memcpy(CSN,data,8);
memcpy(CCNR,data+16,8);
if(isOK <= 1){
PrintAndLog("Failed to obtain CC! Aborting");
return 1;
}
PrintAndLog("CSN: %s",sprint_hex(CSN,8));
return 0;
}
int CmdHFiClass_SendReadBlock(uint8_t blockno,uint8_t *rdata){
UsbCommand d = {CMD_ICLASS_READBLOCK, {blockno}};
memcpy(d.d.asBytes,rdata,sizeof(uint8_t *));
SendCommand(&d);
return 0;
}
int CmdHFiClassList(const char *Cmd) int CmdHFiClassList(const char *Cmd)
{ {
PrintAndLog("Deprecated command, use 'hf list iclass' instead"); PrintAndLog("Deprecated command, use 'hf list iclass' instead");
@ -230,162 +345,124 @@ int CmdHFiClassReader_Replay(const char *Cmd)
return 0; return 0;
} }
int usage_hf_iclass_dump(){
PrintAndLog("Usage: hf iclass dump [e]");
PrintAndLog(" Key - A 16 byte master key");
PrintAndLog(" e - If 'e' is specified, HS_KEY will be used otherwise standard key");
return 0;
}
int CmdHFiClassReader_Dump(const char *Cmd) int CmdHFiClassReader_Dump(const char *Cmd)
{ {
uint8_t readerType = 0; uint8_t readerType = 0;
uint8_t MAC[4]={0x00,0x00,0x00,0x00}; uint8_t MAC[4]={0x00,0x00,0x00,0x00};
uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t keytable[128] = {0}; uint8_t keytable[128] = {0};
int elite = 0; int elite = 0;
uint8_t *used_key; uint8_t *used_key;
int i; int i;
if (strlen(Cmd)<1)
{ if (param_getchar(Cmd, 0) == 'e')
PrintAndLog("Usage: hf iclass dump <Key> [e]"); {
PrintAndLog(" Key - A 16 byte master key"); PrintAndLog("Elite switch on");
PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte"); elite = 1;
PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack"); memcpy(KEY,HS_KEY,sizeof(KEY));
PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format"); //calc h2
PrintAndLog(" sample: hf iclass dump 0011223344556677"); hash2(KEY, keytable);
//printarr_human_readable("keytable", keytable, 128);
}
else
memcpy(KEY,GLOBAL_KEY,sizeof(KEY));
UsbCommand resp;
uint8_t key_sel[8] = {0};
uint8_t key_sel_p[8] = { 0 };
// send ACK
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
return 1;
return 0; //Status 2 or higher
}
if(elite)
if (param_gethex(Cmd, 0, KEY, 16)) {
{ //Get the key index (hash1)
PrintAndLog("KEY must include 16 HEX symbols"); uint8_t key_index[8] = {0};
return 1;
} hash1(CSN, key_index);
//printvar("hash1", key_index,8);
if (param_getchar(Cmd, 1) == 'e') for(i = 0; i < 8 ; i++)
{ key_sel[i] = keytable[key_index[i]] & 0xFF;
PrintAndLog("Elite switch on"); //PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
elite = 1; //printvar("k_sel", key_sel,8);
//Permute from iclass format to standard format
//calc h2 permutekey_rev(key_sel,key_sel_p);
hash2(KEY, keytable); used_key = key_sel_p;
printarr_human_readable("keytable", keytable, 128); }else{
used_key = KEY;
} }
UsbCommand resp; //PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
uint8_t key_sel[8] = {0}; //printvar("Used key",used_key,8);
uint8_t key_sel_p[8] = { 0 }; diversifyKey(CSN,used_key, div_key);
//PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
UsbCommand c = {CMD_READER_ICLASS, {0}}; //printvar("Div key", div_key, 8);
c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC; //printvar("CC_NR:",CCNR,12);
SendCommand(&c); doMAC(CCNR,div_key, MAC);
//printvar("MAC", MAC, 4);
uint8_t iclass_data[32000] = {0};
if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) uint32_t iclass_datalen = 0;
{ uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
PrintAndLog("Command execute timeout");
return 0; UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
} memcpy(d.d.asBytes, MAC, 4);
clearCommandBuffer();
uint8_t isOK = resp.arg[0] & 0xff; SendCommand(&d);
uint8_t * data = resp.d.asBytes; PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
while (true) {
memcpy(CSN,data,8); printf(".");
memcpy(CCNR,data+16,8); if (ukbhit()) {
getchar();
PrintAndLog("isOk:%02x", isOK); printf("\naborted via keyboard!\n");
break;
if(isOK > 0) }
{ if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
PrintAndLog("CSN: %s",sprint_hex(CSN,8)); {
} uint32_t dataLength = resp.arg[0];
if(isOK <= 1){ iclass_blocksFailed |= resp.arg[1];
PrintAndLog("Failed to obtain CC! Aborting"); if(dataLength > 0)
return 0; {
} PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
//Status 2 or higher memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
iclass_datalen += dataLength;
if(elite) }else
{ {//Last transfer, datalength 0 means the dump is finished
//Get the key index (hash1) PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
uint8_t key_index[8] = {0}; if(iclass_blocksFailed)
{
hash1(CSN, key_index); PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
printvar("hash1", key_index,8); }
for(i = 0; i < 8 ; i++) if(iclass_datalen > 0)
key_sel[i] = keytable[key_index[i]] & 0xFF; {
PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:"); char filename[100] = {0};
printvar("k_sel", key_sel,8); //create a preferred filename
//Permute from iclass format to standard format snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
permutekey_rev(key_sel,key_sel_p); CSN[0],CSN[1],CSN[2],CSN[3],
used_key = key_sel_p; CSN[4],CSN[5],CSN[6],CSN[7]);
}else{ //Place the div_key in block 3
used_key = KEY; memcpy(iclass_data+(3*8), div_key, 8);
} saveFile(filename,"bin",iclass_data, iclass_datalen );
}
PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:"); //Aaaand we're finished
printvar("Used key",used_key,8); return 0;
diversifyKey(CSN,used_key, div_key); }
PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):"); }
printvar("Div key", div_key, 8); }
printvar("CC_NR:",CCNR,12); return 0;
doMAC(CCNR,div_key, MAC);
printvar("MAC", MAC, 4);
uint8_t iclass_data[32000] = {0};
uint32_t iclass_datalen = 0;
uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
memcpy(d.d.asBytes, MAC, 4);
clearCommandBuffer();
SendCommand(&d);
PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
while (true) {
printf(".");
if (ukbhit()) {
getchar();
printf("\naborted via keyboard!\n");
break;
}
if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
{
uint32_t dataLength = resp.arg[0];
iclass_blocksFailed |= resp.arg[1];
if(dataLength > 0)
{
PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
iclass_datalen += dataLength;
}else
{//Last transfer, datalength 0 means the dump is finished
PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
if(iclass_blocksFailed)
{
PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
}
if(iclass_datalen > 0)
{
char filename[100] = {0};
//create a preferred filename
snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
CSN[0],CSN[1],CSN[2],CSN[3],
CSN[4],CSN[5],CSN[6],CSN[7]);
//Place the div_key in block 3
memcpy(iclass_data+(3*8), div_key, 8);
saveFile(filename,"bin",iclass_data, iclass_datalen );
}
//Aaaand we're finished
return 0;
}
}
}
return 0;
} }
int hf_iclass_eload_usage() int hf_iclass_eload_usage()
@ -477,31 +554,6 @@ int usage_hf_iclass_decrypt()
return 1; return 1;
} }
int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
{
FILE *f = fopen(filename, "rb");
if(!f) {
PrintAndLog("Failed to read from file '%s'", filename);
return 1;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
size_t bytes_read = fread(buffer, 1, len, f);
fclose(f);
if(fsize != len)
{
PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
return 1;
}
if(bytes_read != len)
{
PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
return 1;
}
return 0;
}
int CmdHFiClassDecrypt(const char *Cmd) int CmdHFiClassDecrypt(const char *Cmd)
{ {
uint8_t key[16] = { 0 }; uint8_t key[16] = { 0 };
@ -559,83 +611,51 @@ int CmdHFiClassDecrypt(const char *Cmd)
return 0; return 0;
} }
void Calc_wb_mac(uint8_t blockno,uint8_t *data,uint8_t *div_key,uint8_t MAC[4]){
uint8_t WB[9];
WB[0] = blockno;
memcpy(WB + 1,data,8);
// do mac 9 bytes
doMAC_N(WB,sizeof(WB),div_key,MAC);
}
int CmdHFiClass_iso14443A_write(const char *Cmd) int CmdHFiClass_iso14443A_write(const char *Cmd)
{ {
uint8_t readerType = 0; uint8_t blockno=0;
uint8_t MAC[4]={0x00,0x00,0x00,0x00};
uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t blockNo=0;
uint8_t bldata[8]={0}; uint8_t bldata[8]={0};
uint8_t MAC[4]={0x00,0x00,0x00,0x00};
if (strlen(Cmd)<3) uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
{ uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>"); uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA"); uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
return 0;
}
if (param_gethex(Cmd, 0, KEY, 16)) if (param_gethex(Cmd, 0,&blockno, 2))
{ {
PrintAndLog("KEY must include 16 HEX symbols"); PrintAndLog("Block No must include 2 HEX symbols");
return 1; return 1;
} }
if (param_gethex(Cmd, 1, bldata, 16))
{
PrintAndLog("Block data must include 16 HEX symbols");
return 1;
}
// tell the reader to send ACK and get CSN + CCNR
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
return 1;
memcpy(KEY,GLOBAL_KEY,sizeof(KEY));
diversifyKey(CSN,KEY, div_key);
doMAC(CCNR,div_key, MAC);
// send authentication
CmdHFiClass_SendAuthentication(MAC);
// send write command
Calc_wb_mac(blockno,bldata,div_key,MAC);
UsbCommand w = {CMD_ICLASS_ISO14443A_WRITE, {blockno}};
memcpy(w.d.asBytes, bldata, 8);
memcpy(w.d.asBytes + 8,MAC, 4);
blockNo = param_get8(Cmd, 1); SendCommand(&w);
if (blockNo>32) return 0;
{
PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
return 1;
}
if (param_gethex(Cmd, 2, bldata, 8))
{
PrintAndLog("Block data must include 8 HEX symbols");
return 1;
}
UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
uint8_t isOK = resp.arg[0] & 0xff;
uint8_t * data = resp.d.asBytes;
memcpy(CSN,data,8);
memcpy(CCNR,data+8,8);
PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
diversifyKey(CSN,KEY, div_key);
PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
doMAC(CCNR, div_key, MAC);
UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
memcpy(c2.d.asBytes, bldata, 8);
memcpy(c2.d.asBytes+8, MAC, 4);
SendCommand(&c2);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
uint8_t * data = resp.d.asBytes;
if (isOK)
PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
else
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
return 0;
} }
int CmdHFiClass_loclass(const char *Cmd) int CmdHFiClass_loclass(const char *Cmd)
{ {
@ -682,23 +702,406 @@ int CmdHFiClass_loclass(const char *Cmd)
return 0; return 0;
} }
int usage_hf_iclass_readtagfile(){
static command_t CommandTable[] = PrintAndLog("Usage: hf iclass readtagfile <filename>");
return 1;
}
void printIclassDumpContents(uint8_t* iclass_dump,uint8_t startblock,uint8_t endblock,size_t filesize){
uint8_t blockdata[8];
uint8_t mem_config;
memcpy(&mem_config, iclass_dump + 13,1);
uint8_t maxmemcount;
uint8_t filemaxblock = filesize / 8;
if (mem_config == 0x80)
maxmemcount = 255;
else
maxmemcount = 32;
if (startblock == 0)
startblock = 6;
if ((endblock > maxmemcount) || (endblock == 0))
endblock = maxmemcount;
if (endblock > filemaxblock)
endblock = filemaxblock;
int i = startblock;
int j;
while (i < endblock){
printf("block[%02x]: ",i);
memcpy(blockdata,iclass_dump + (i * 8),8);
for (j = 0;j < 8;j++)
printf("%02x",blockdata[j]);
printf("\n");
i++;
}
if ((i < filemaxblock) && (i < maxmemcount)){
printf("block[%02x]: ",i);
memcpy(blockdata,iclass_dump + (i * 8),8);
for (j = 0;j < 8;j++)
printf("%02x",blockdata[j]);
printf("\n");
}
}
int CmdHFiClassReadTagFile(const char *Cmd)
{ {
{"help", CmdHelp, 1, "This help"}, int startblock = 0;
{"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"}, int endblock = 0;
{"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, char tempnum[5];
{"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, FILE *f;
{"reader",CmdHFiClassReader, 0, "Read an iClass tag"}, char filename[FILE_PATH_SIZE];
{"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, if (param_getstr(Cmd, 0, filename) < 1)
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, return usage_hf_iclass_readtagfile();
// {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
{"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"}, startblock = 0;
{"eload", CmdHFiClassELoad, 0, "[experimental] Load data into iclass emulator memory"}, else
{"decrypt", CmdHFiClassDecrypt, 1, "Decrypt tagdump" }, sscanf(tempnum,"%d",&startblock);
{NULL, NULL, 0, NULL}
}; if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
endblock = 0;
else
sscanf(tempnum,"%d",&endblock);
// file handling and reading
f = fopen(filename,"rb");
if(!f) {
PrintAndLog("Failed to read from file '%s'", filename);
return 1;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *dump = malloc(fsize);
size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f);
uint8_t *csn = dump;
printf("CSN : %02x %02x %02x %02x %02x %02x %02x %02x\n",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
// printIclassDumpInfo(dump);
printIclassDumpContents(dump,startblock,endblock,bytes_read);
free(dump);
return 0;
}
int usage_hf_iclass_calckey(){
PrintAndLog("error please load ekey");
return 1;
}
uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv){
uint64_t new_div = 0x00;
new_div ^= sdiv;
new_div ^= hdiv;
return new_div;
}
uint64_t hexarray_to_uint64(uint8_t *key){
char temp[17];
uint64_t uint_key;
for (int i = 0;i < 8;i++)
sprintf(&temp[(i *2)],"%02X",key[i]);
temp[16] = '\0';
if (sscanf(temp,"%016llX",&uint_key) < 1)
return 0;
return uint_key;
}
int CmdHFiClassCalcEKey(const char *Cmd){
uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t std_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t elite_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t keytable[128] = {0};
uint8_t key_index[8] = {0};
uint64_t new_div_key;
uint64_t i_elite_div_key;
uint64_t i_std_div_key;
int i;
if (!HS_KEY_LOAD)
return usage_hf_iclass_calckey();
hash2(HS_KEY, keytable);
UsbCommand resp;
uint8_t key_sel[8] = {0};
uint8_t key_sel_p[8] = { 0 };
UsbCommand c = {CMD_READER_ICLASS, {0}};
c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
{
PrintAndLog("Command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
uint8_t * data = resp.d.asBytes;
memcpy(CSN,data,8);
// PrintAndLog("isOk:%02x", isOK);
if(isOK > 0)
{
PrintAndLog("CSN: %s",sprint_hex(CSN,8));
}
if(isOK <= 1){
PrintAndLog("Failed to obtain CC! Aborting");
return 0;
}
diversifyKey(CSN, GLOBAL_KEY, std_div_key);
// printvar("(S)Div key", std_div_key, 8);
hash1(CSN, key_index);
for(i = 0; i < 8 ; i++)
key_sel[i] = keytable[key_index[i]] & 0xFF;
//Permute from iclass format to standard format
permutekey_rev(key_sel,key_sel_p);
diversifyKey(CSN,key_sel_p, elite_div_key);
// printvar("(E)Div key", elite_div_key, 8);
i_elite_div_key = hexarray_to_uint64(elite_div_key);
i_std_div_key = hexarray_to_uint64(std_div_key);
new_div_key = xorcheck(i_std_div_key,i_elite_div_key);
printf("(E)Div key : %016llx\n",new_div_key);
return 0;
}
int usage_hf_iclass_load(){
PrintAndLog("Usage: hf iclass load <tagfile.bin> <start block> <end block>");
PrintAndLog(" sample: hf iclass write iclass_tagdump-121345.bin 6 19");
return -1;
}
// load data from tag file and write to another iclass tag
int CmdHFiClass_load(const char *Cmd){
if (strlen(Cmd) < 3)
return usage_hf_iclass_load();
int startblock = 0;
int endblock = 0;
char tempnum[5];
uint8_t mem_config;
FILE *f;
char filename[FILE_PATH_SIZE];
if (param_getstr(Cmd, 0, filename) < 1)
return usage_hf_iclass_load();
if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
startblock = 6;
else
sscanf(tempnum,"%d",&startblock);
if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
endblock = 0;
else
sscanf(tempnum,"%d",&endblock);
// file handling and reading
f = fopen(filename,"rb");
if(!f) {
PrintAndLog("Failed to read from file '%s'", filename);
return 1;
}
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *dump = malloc(fsize);
size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f);
memcpy(&mem_config,dump + 13,1);
uint8_t maxmemcount;
uint8_t filemaxblock = bytes_read / 8;
if (mem_config == 0x80)
maxmemcount = 255;
else
maxmemcount = 32;
if (startblock == 0)
startblock = 6;
if ((endblock > maxmemcount) || (endblock == 0))
endblock = maxmemcount;
if (endblock > filemaxblock)
endblock = filemaxblock;
return 0;
}
int CmdHFIClassReadBlock(const char *Cmd){
uint8_t blockno=0;
uint8_t MAC[4]={0x00,0x00,0x00,0x00};
uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
if (param_gethex(Cmd, 0,&blockno, 2))
{
PrintAndLog("Block No must include 2 HEX symbols");
return 1;
}
// tell the reader to send ACK and get CSN + CCNR
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
return 1;
memcpy(KEY,GLOBAL_KEY,sizeof(KEY));
// PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
// printvar("Used key",KEY,8);
diversifyKey(CSN,KEY, div_key);
// PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
// printvar("Div key", div_key, 8);
// printvar("CC_NR:",CCNR,8);
doMAC(CCNR,div_key, MAC);
// printvar("MAC", MAC, 4);
CmdHFiClass_SendAuthentication(MAC);
// not yet implement
return 0;
}
int CmdHFiClassCloneTag_Usage(){
PrintAndLog("Usage: hf iclass clone <tagfile.bin> <start block> <end block> -e <KEY>");
PrintAndLog(" sample: hf iclass clone iclass_tagdump-121345.bin 6 19 -e 1122334455667788");
return -1;
}
int CmdHFiClassCloneTag(const char *Cmd){
if (strlen(Cmd) < 3)
return CmdHFiClassCloneTag_Usage();
int startblock = 0;
int endblock = 0;
char tempnum[5];
FILE *f;
iclass_block_t tag_data[26];
uint8_t MAC[4]={0x00,0x00,0x00,0x00};
uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
char filename[FILE_PATH_SIZE];
// get tagfile parameter
if (param_getstr(Cmd, 0, filename) < 1)
return usage_hf_iclass_load();
// get start block parameter
if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
startblock = 6;
else
sscanf(tempnum,"%x",&startblock);
// get end block parameter
if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
endblock = 0;
else
sscanf(tempnum,"%x",&endblock);
// file handling and reading
f = fopen(filename,"rb");
if(!f) {
PrintAndLog("Failed to read from file '%s'", filename);
return 1;
}
// now read data from the file from block 6 --- 19
// ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
// then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time,
// else we have to create a share memory
int i;
fseek(f,6*8,SEEK_SET);
fread(tag_data,sizeof(iclass_block_t),32 - 6,f);
for (i = 0;i < 32 - 6; i++){
printf("block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]\n",i + 6,tag_data[i].d[0],tag_data[i].d[1],tag_data[i].d[2],tag_data[i].d[3],tag_data[i].d[4],tag_data[i].d[5],tag_data[i].d[6],tag_data[i].d[7]);
}
// tell the reader to send ACK and get CSN + CCNR
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
return 1;
memcpy(KEY,GLOBAL_KEY,sizeof(KEY));
// PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
// printvar("Used key",KEY,8);
diversifyKey(CSN,KEY, div_key);
// PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
// printvar("Div key", div_key, 8);
// printvar("CC_NR:",CCNR,8);
doMAC(CCNR,div_key, MAC);
// printvar("MAC", MAC, 4);
// now authentication with the card
CmdHFiClass_SendAuthentication(MAC);
// everythings is ready now
UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
uint8_t *ptr;
// calculate all mac for every the block we will write
for (i = startblock;i <= endblock;i++){
Calc_wb_mac(i,tag_data[i - 6].d,div_key,MAC);
// usb command d start pointer = d + (i - 6) * 12
// memcpy(pointer,tag_data[i - 6],8) 8 bytes
// memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
// next one
ptr = w.d.asBytes + (i - 6) * 12;
memcpy(ptr, &(tag_data[i - 6].d[0]), 8);
memcpy(ptr + 8,MAC, 4);
}
uint8_t p[12];
for (i = 0; i <= endblock - startblock;i++){
memcpy(p,w.d.asBytes + (i * 12),12);
printf("block [%02x]",i + 6);
printf(" [%02x%02x%02x%02x%02x%02x%02x%02x]",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
printf(" MAC [%02x%02x%02x%02x]\n",p[8],p[9],p[10],p[11]);
}
SendCommand(&w);
return 0;
}
int CmdHFiClassEKey_usage(){
PrintAndLog(" Usage: hf iclass ekey [filename] to load the key");
PrintAndLog("Sample: hf iclass ekey helloworld.key [load key from file]");
PrintAndLog("Sample: hf iclass ekey [show the current ekey]");
return -1;
}
int CmdHFiClassEKey(const char *Cmd){
if (strlen(Cmd) > 1)
{
if (readKeyfile(Cmd,sizeof(HS_KEY),HS_KEY) != 0)
{
HS_KEY_LOAD = false;
memcpy(HS_KEY,BLANK_KEY,sizeof(BLANK_KEY));
return CmdHFiClassEKey_usage();
}
HS_KEY_LOAD = true;
}
else
CmdHFiClass_printkey("HS Key",HS_KEY);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"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"},
{"read", CmdHFIClassReadBlock, 0, "Authenticate and Read iClass block"},
{"load", CmdHFiClass_load, 0, "Load from tagfile to iclass card"},
{"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
{"eload", CmdHFiClassELoad, 0, "[experimental] Load data into iclass emulator memory"},
{"decrypt", CmdHFiClassDecrypt, 1, "Decrypt tagdump" },
{"readtagfile", CmdHFiClassReadTagFile, 1, "Display Content from tagfile"},
{"ediv", CmdHFiClassCalcEKey, 0, "Give Diversify key for this card to write to block 3"},
{"readkey", CmdHFiClassReadKeyFile, 1, "Read and display key from file"},
{"savekey", CmdHFiClassSaveKeyFile, 1, "Write key to file"},
{"clone", CmdHFiClassCloneTag, 0, "Clone tag"},
{"ekey", CmdHFiClassEKey, 1, "Load HS key from file or show current HS Key"},
{NULL, NULL, 0, NULL}
};
int CmdHFiClass(const char *Cmd) int CmdHFiClass(const char *Cmd)
{ {
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);

9
client/cmdhficlass.h Normal file → Executable file
View file

@ -1,3 +1,5 @@
// version 2.1.0
// add readkeyfile,writekeyfile,modify dump,iso write and calcEkey functions.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com> // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
// Copyright (C) 2011 Gerhard de Koning Gans // Copyright (C) 2011 Gerhard de Koning Gans
@ -20,5 +22,10 @@ int CmdHFiClassList(const char *Cmd);
int HFiClassReader(const char *Cmd, bool loop, bool verbose); int HFiClassReader(const char *Cmd, bool loop, bool verbose);
int CmdHFiClassReader(const char *Cmd); int CmdHFiClassReader(const char *Cmd);
int CmdHFiClassReader_Replay(const char *Cmd); int CmdHFiClassReader_Replay(const char *Cmd);
int CmdHFiClassReadKeyFile(const char *filename);
int CmdHFiClassWriteKeyFile(const char *Cmd);
int CmdHFiClass_iso14443A_write(const char *Cmd);
int CmdHFiClassCalcEKey(const char *Cmd);
int CmdHFiClassRestore(const char *cmd);
int CmdHFiClass_TestMac(const char *Cmd);
#endif #endif

View file

@ -30,7 +30,7 @@
#include "cmdlfpcf7931.h" #include "cmdlfpcf7931.h"
#include "cmdlfio.h" #include "cmdlfio.h"
#include "lfdemod.h" #include "lfdemod.h"
#include "cmdlfviking.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/* send a command before reading */ /* send a command before reading */
@ -1148,6 +1148,7 @@ static command_t CommandTable[] =
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"}, {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
{"viking", CmdLFViking, 1, "{Viking RFIDs..}"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

64
client/cmdlfviking.c Executable file
View file

@ -0,0 +1,64 @@
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfviking.h"
#include "lfdemod.h"
static int CmdHelp(const char *Cmd);
int CmdVikingDemod(const char *Cmd)
{
uint8_t id[4];
if (param_gethex(Cmd,0,id,8) == 1)
{
PrintAndLog("Usage: lf viking demod <CardID 8 bytes of hex number>");
return 0;
}
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {false,0,0}};
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
getSamples("40000",true);
// try to demod AMViking
return AMVikingDemod(id);
}
int CmdVikingClone(const char *Cmd)
{
uint32_t b1,b2;
// get the tag number 64 bits (8 bytes) in hex
uint8_t id[8];
if (param_gethex(Cmd,0,id,16) == 1)
{
PrintAndLog("Usage: lf viking clone <Card ID 16 bytes of hex number>");
return 0;
}
b1 = bytes_to_num(id,sizeof(uint32_t));
b2 = bytes_to_num(id + sizeof(uint32_t),sizeof(uint32_t));
UsbCommand c = {CMD_VIKING_CLONE_TAG,{b1,b2}};
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"demod",CmdVikingDemod ,1, "<8 digits tag id> -- Extract tag data"},
{"clone", CmdVikingClone, 1, "<16 digits card data> clone viking tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFViking(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

7
client/cmdlfviking.h Executable file
View file

@ -0,0 +1,7 @@
#ifndef CMDLFVIKING_H__
#define CMDLFVIKING_H__
int CmdLFViking(const char *Cmd);
int CmdVikingDemod(const char *Cmd);
int CmdVikingClone(const char *Cmd);
#endif

View file

@ -241,6 +241,27 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
//free(cc_nr); //free(cc_nr);
return; return;
} }
void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4])
{
uint8_t *cc_nr;
uint8_t div_key[8];
cc_nr = (uint8_t*) malloc(cc_nr_size);
memcpy(cc_nr,cc_nr_p,cc_nr_size);
memcpy(div_key,div_key_p,8);
reverse_arraybytes(cc_nr,cc_nr_size);
BitstreamIn bitstream = {cc_nr,cc_nr_size * 8,0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
free(cc_nr);
return;
}
#ifndef ON_DEVICE #ifndef ON_DEVICE
int testMAC() int testMAC()
{ {

View file

@ -42,6 +42,8 @@
#include <stdint.h> #include <stdint.h>
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4]);
#ifndef ON_DEVICE #ifndef ON_DEVICE
int testMAC(); int testMAC();
#endif #endif

View file

@ -453,3 +453,32 @@ void xor(unsigned char *dst, unsigned char *src, size_t len) {
int32_t le24toh (uint8_t data[3]) { int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0]; return (data[2] << 16) | (data[1] << 8) | data[0];
} }
size_t bytes_to_bits(const uint8_t *src,size_t src_size,uint8_t *des,size_t des_size){
int i,j,k;
int count = 0;
// check src_size and des_size
if ((src_size * 8) > des_size)
return -1;
// convert 1 bytes to 8 bits at the time
for (j = 0;j < src_size;j++){
for (i = 0;i < 8;i++){
k = src[j] >> i;
if (k & 1)
*(des + (j * 8) + (7 - i)) = 1;
else
*(des + (j * 8) + (7 - i)) = 0;
count++;
}
}
return count;
}
void print_arraybinary(const uint8_t *b,size_t c){
int i;
for (i = 0;i < c;i++){
if (*(b + i) == 0)
printf("0");
else
printf("1");
}
printf("\n");
}

View file

@ -65,3 +65,4 @@ void wiegand_add_parity(char *target, char *source, char length);
void xor(unsigned char *dst, unsigned char *src, size_t len); void xor(unsigned char *dst, unsigned char *src, size_t len);
int32_t le24toh(uint8_t data[3]); int32_t le24toh(uint8_t data[3]);
size_t bytes_to_bits(const uint8_t *src,size_t src_size,uint8_t *des,size_t des_size);

View file

@ -1482,3 +1482,26 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
*size = numBits; *size = numBits;
return errCnt; return errCnt;
} }
// on successful return 1 otherwise return 0
int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bits,size_t id_bits_size)
{
//no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future
// otherwise could be a void with no arguments
//set defaults
uint32_t i = 0;
uint32_t lastcheckindex = size - (id_bits_size * 2);
int found = 0;
while (i < lastcheckindex)
{
if (memcmp(BitStream + i,id_bits,id_bits_size) == 0)
{
*startIdx = i;
found = 1;
break;
}
i++;
}
return found;
}

View file

@ -49,5 +49,6 @@ int IOdemodFSK(uint8_t *dest, size_t size);
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert); int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int PyramiddemodFSK(uint8_t *dest, size_t *size); int PyramiddemodFSK(uint8_t *dest, size_t *size);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo); int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bit,size_t id_bits_size);
#endif #endif

View file

@ -96,6 +96,8 @@ typedef struct{
#define CMD_ASK_SIM_TAG 0x021F #define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220 #define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221 #define CMD_AWID_DEMOD_FSK 0x0221
#define CMD_VIKING_CLONE_TAG 0x0222
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
@ -135,6 +137,9 @@ typedef struct{
#define CMD_READER_ICLASS_REPLAY 0x0395 #define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_ISO14443A_WRITE 0x0397 #define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398 #define CMD_ICLASS_EML_MEMSET 0x0398
#define CMD_ICLASS_AUTHENTICATION 0x0399
#define CMD_ICLASS_READBLOCK 0x039A
#define CMD_ICLASS_CLONE 0x039B
// For measurements of the antenna tuning // For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400 #define CMD_MEASURE_ANTENNA_TUNING 0x0400