mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-23 14:35:28 -07:00
lf viking and iclass
add lf viking add Iclass write
This commit is contained in:
parent
b067125f98
commit
7f99524209
20 changed files with 970 additions and 400 deletions
|
@ -684,6 +684,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
|
||||
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
|
||||
break;
|
||||
case CMD_VIKING_CLONE_TAG:
|
||||
CopyViKingtoT55x7(c->arg[0],c->arg[1]);
|
||||
break;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HITAG
|
||||
|
@ -868,6 +873,16 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
|||
case CMD_ICLASS_EML_MEMSET:
|
||||
emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
|
||||
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
|
||||
|
||||
case CMD_BUFF_CLEAR:
|
||||
|
|
|
@ -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_Replay(uint8_t arg0,uint8_t *MAC);
|
||||
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
|
||||
void SnoopHitag(uint32_t type);
|
||||
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
|
||||
|
|
160
armsrc/iclass.c
160
armsrc/iclass.c
|
@ -1903,131 +1903,57 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
|||
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//2. Create Read method (cut-down from above) based off responses from 1.
|
||||
// Since we have the MAC could continue to use replay function.
|
||||
//3. Create Write method
|
||||
/*
|
||||
void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) {
|
||||
uint8_t act_all[] = { 0x0a };
|
||||
uint8_t identify[] = { 0x0c };
|
||||
uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t readcheck_cc[]= { 0x88, 0x02 };
|
||||
void IClass_Authentication(uint8_t *MAC){
|
||||
uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE];
|
||||
memcpy(check+5,MAC,4);
|
||||
|
||||
sendCmdGetResponseWithRetries(check, sizeof(check),resp, 8, 5);
|
||||
// successful
|
||||
}
|
||||
void IClass_iso14443A_write(uint8_t blockNo, uint8_t *data) {
|
||||
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
uint16_t crc = 0;
|
||||
write[1] = blockNo;
|
||||
memcpy(write + 2,data,8); // data
|
||||
memcpy(write+10,data + 8,4); // mac no
|
||||
uint8_t r[12];
|
||||
|
||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
|
||||
// 0x87
|
||||
sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5);
|
||||
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]);
|
||||
|
||||
// Reset trace buffer
|
||||
memset(trace, 0x44, RECV_CMD_OFFSET);
|
||||
traceLen = 0;
|
||||
|
||||
// Setup SSC
|
||||
FpgaSetupSsc();
|
||||
// Start from off (no field generated)
|
||||
// Signal field is off with the appropriate LED
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Now give it time to spin up.
|
||||
// Signal field is on with the appropriate LED
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
SpinDelay(200);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
for(int i=0;i<1;i++) {
|
||||
|
||||
if(traceLen > TRACE_SIZE) {
|
||||
DbpString("Trace full");
|
||||
break;
|
||||
if (memcmp(data,r,8) == 0)
|
||||
Dbprintf("Write block [%02x] ok",blockNo);
|
||||
else
|
||||
Dbprintf("Write block [%02x] fail",blockNo);
|
||||
}
|
||||
void IClass_Clone(uint8_t startblock,uint8_t endblock,uint8_t *data){
|
||||
uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t r[12];
|
||||
int i;
|
||||
int written = 0;
|
||||
int total_block = (endblock - startblock) + 1;
|
||||
for (i = 0; i < total_block;i++){
|
||||
// block number
|
||||
write[0] = 0x87;
|
||||
write[1] = i + startblock;
|
||||
// data
|
||||
memcpy(write + 2,data + (i * 12),8);
|
||||
// mac number
|
||||
memcpy(write + 10,data + ((i * 12) + 8), 4);
|
||||
sendCmdGetResponseWithRetries(write,sizeof(write),r,sizeof(r),5);
|
||||
|
||||
if (BUTTON_PRESS()) break;
|
||||
|
||||
// Send act_all
|
||||
ReaderTransmitIClass(act_all, 1);
|
||||
// Card present?
|
||||
if(ReaderReceiveIClass(resp)) {
|
||||
ReaderTransmitIClass(identify, 1);
|
||||
if(ReaderReceiveIClass(resp) == 10) {
|
||||
// Select card
|
||||
memcpy(&select[1],resp,8);
|
||||
ReaderTransmitIClass(select, sizeof(select));
|
||||
|
||||
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]);
|
||||
if (memcmp(write + 2,r,8) == 0){
|
||||
Dbprintf("Write block [%02x] ok",i + 6);
|
||||
written++;
|
||||
}
|
||||
// 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;
|
||||
else
|
||||
Dbprintf("Write block [%02x] fail",i + 6);
|
||||
}
|
||||
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 (written == total_block)
|
||||
Dbprintf("Clone complete");
|
||||
else
|
||||
Dbprintf("Clone incomplete");
|
||||
|
||||
}
|
||||
}
|
||||
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();
|
||||
}*/
|
||||
|
|
|
@ -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
|
||||
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
1
client/.history
Normal file
|
@ -0,0 +1 @@
|
|||
lf
|
|
@ -93,6 +93,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdlfem4x.c \
|
||||
cmdlfhitag.c \
|
||||
cmdlfti.c \
|
||||
cmdlfviking.c\
|
||||
cmdparser.c \
|
||||
cmdmain.c \
|
||||
cmdlft55xx.c \
|
||||
|
|
|
@ -1870,6 +1870,53 @@ int CmdRawDemod(const char *Cmd)
|
|||
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)
|
||||
{
|
||||
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)"},
|
||||
{"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase 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"},
|
||||
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"},
|
||||
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"},
|
||||
|
|
|
@ -67,7 +67,8 @@ int PSKDemod(const char *Cmd, bool verbose);
|
|||
int NRZrawDemod(const char *Cmd, bool verbose);
|
||||
void printEM410x(uint32_t hi, uint64_t id);
|
||||
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)
|
||||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
|
|
697
client/cmdhficlass.c
Normal file → Executable file
697
client/cmdhficlass.c
Normal file → Executable file
|
@ -31,9 +31,14 @@
|
|||
#include "loclass/fileutils.h"
|
||||
#include "protocols.h"
|
||||
#include "usb_cmd.h"
|
||||
|
||||
typedef struct iclass_block {
|
||||
uint8_t d[8];
|
||||
} iclass_block_t;
|
||||
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)
|
||||
{
|
||||
uint8_t res = val ^ (val >> 1); //1st pass
|
||||
|
@ -42,7 +47,117 @@ int xorbits_8(uint8_t val)
|
|||
res = res ^ (res >> 4); // 4th pass
|
||||
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)
|
||||
{
|
||||
PrintAndLog("Deprecated command, use 'hf list iclass' instead");
|
||||
|
@ -230,7 +345,12 @@ int CmdHFiClassReader_Replay(const char *Cmd)
|
|||
|
||||
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)
|
||||
{
|
||||
uint8_t readerType = 0;
|
||||
|
@ -244,68 +364,27 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
int elite = 0;
|
||||
uint8_t *used_key;
|
||||
int i;
|
||||
if (strlen(Cmd)<1)
|
||||
{
|
||||
PrintAndLog("Usage: hf iclass dump <Key> [e]");
|
||||
PrintAndLog(" Key - A 16 byte master key");
|
||||
PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
|
||||
PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
|
||||
PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
|
||||
PrintAndLog(" sample: hf iclass dump 0011223344556677");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 0, KEY, 16))
|
||||
{
|
||||
PrintAndLog("KEY must include 16 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (param_getchar(Cmd, 1) == 'e')
|
||||
if (param_getchar(Cmd, 0) == 'e')
|
||||
{
|
||||
PrintAndLog("Elite switch on");
|
||||
elite = 1;
|
||||
|
||||
memcpy(KEY,HS_KEY,sizeof(KEY));
|
||||
//calc h2
|
||||
hash2(KEY, keytable);
|
||||
printarr_human_readable("keytable", keytable, 128);
|
||||
|
||||
//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 };
|
||||
|
||||
UsbCommand c = {CMD_READER_ICLASS, {0}};
|
||||
c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
|
||||
SendCommand(&c);
|
||||
// send ACK
|
||||
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
|
||||
return 1;
|
||||
|
||||
|
||||
|
||||
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);
|
||||
memcpy(CCNR,data+16,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;
|
||||
}
|
||||
//Status 2 or higher
|
||||
|
||||
if(elite)
|
||||
|
@ -314,11 +393,11 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
uint8_t key_index[8] = {0};
|
||||
|
||||
hash1(CSN, key_index);
|
||||
printvar("hash1", key_index,8);
|
||||
//printvar("hash1", key_index,8);
|
||||
for(i = 0; i < 8 ; i++)
|
||||
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:");
|
||||
printvar("k_sel", key_sel,8);
|
||||
//PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
|
||||
//printvar("k_sel", key_sel,8);
|
||||
//Permute from iclass format to standard format
|
||||
permutekey_rev(key_sel,key_sel_p);
|
||||
used_key = key_sel_p;
|
||||
|
@ -326,14 +405,14 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
used_key = KEY;
|
||||
}
|
||||
|
||||
PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
|
||||
printvar("Used key",used_key,8);
|
||||
//PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
|
||||
//printvar("Used key",used_key,8);
|
||||
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);
|
||||
//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);
|
||||
doMAC(CCNR,div_key, MAC);
|
||||
printvar("MAC", MAC, 4);
|
||||
//printvar("MAC", MAC, 4);
|
||||
|
||||
uint8_t iclass_data[32000] = {0};
|
||||
uint32_t iclass_datalen = 0;
|
||||
|
@ -383,8 +462,6 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -477,31 +554,6 @@ int usage_hf_iclass_decrypt()
|
|||
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)
|
||||
{
|
||||
uint8_t key[16] = { 0 };
|
||||
|
@ -559,82 +611,50 @@ int CmdHFiClassDecrypt(const char *Cmd)
|
|||
|
||||
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)
|
||||
{
|
||||
uint8_t readerType = 0;
|
||||
uint8_t blockno=0;
|
||||
uint8_t bldata[8]={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};
|
||||
|
||||
if (strlen(Cmd)<3)
|
||||
if (param_gethex(Cmd, 0,&blockno, 2))
|
||||
{
|
||||
PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
|
||||
PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 0, KEY, 16))
|
||||
{
|
||||
PrintAndLog("KEY must include 16 HEX symbols");
|
||||
PrintAndLog("Block No must include 2 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 1);
|
||||
if (blockNo>32)
|
||||
if (param_gethex(Cmd, 1, bldata, 16))
|
||||
{
|
||||
PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
|
||||
PrintAndLog("Block data must include 16 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
if (param_gethex(Cmd, 2, bldata, 8))
|
||||
{
|
||||
PrintAndLog("Block data must include 8 HEX symbols");
|
||||
// tell the reader to send ACK and get CSN + CCNR
|
||||
if (CmdHFiClass_SendACK(CSN,CCNR) != 0)
|
||||
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");
|
||||
}
|
||||
|
||||
memcpy(KEY,GLOBAL_KEY,sizeof(KEY));
|
||||
diversifyKey(CSN,KEY, div_key);
|
||||
|
||||
PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
|
||||
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);
|
||||
|
||||
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");
|
||||
}
|
||||
SendCommand(&w);
|
||||
return 0;
|
||||
}
|
||||
int CmdHFiClass_loclass(const char *Cmd)
|
||||
|
@ -682,7 +702,383 @@ int CmdHFiClass_loclass(const char *Cmd)
|
|||
|
||||
return 0;
|
||||
}
|
||||
int usage_hf_iclass_readtagfile(){
|
||||
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)
|
||||
{
|
||||
int startblock = 0;
|
||||
int endblock = 0;
|
||||
char tempnum[5];
|
||||
FILE *f;
|
||||
char filename[FILE_PATH_SIZE];
|
||||
if (param_getstr(Cmd, 0, filename) < 1)
|
||||
return usage_hf_iclass_readtagfile();
|
||||
if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
|
||||
startblock = 0;
|
||||
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);
|
||||
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"},
|
||||
|
@ -692,13 +1088,20 @@ static command_t CommandTable[] =
|
|||
{"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"},
|
||||
{"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)
|
||||
{
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
|
|
9
client/cmdhficlass.h
Normal file → Executable file
9
client/cmdhficlass.h
Normal file → Executable 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) 2011 Gerhard de Koning Gans
|
||||
|
@ -20,5 +22,10 @@ int CmdHFiClassList(const char *Cmd);
|
|||
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
|
||||
int CmdHFiClassReader(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
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "cmdlfpcf7931.h"
|
||||
#include "cmdlfio.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
#include "cmdlfviking.h"
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
/* send a command before reading */
|
||||
|
@ -1148,6 +1148,7 @@ static command_t CommandTable[] =
|
|||
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
|
||||
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
|
||||
{"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
|
||||
{"viking", CmdLFViking, 1, "{Viking RFIDs..}"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
64
client/cmdlfviking.c
Executable file
64
client/cmdlfviking.c
Executable 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
7
client/cmdlfviking.h
Executable 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
|
||||
|
|
@ -241,6 +241,27 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
|
|||
//free(cc_nr);
|
||||
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
|
||||
int testMAC()
|
||||
{
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include <stdint.h>
|
||||
|
||||
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
|
||||
int testMAC();
|
||||
#endif
|
||||
|
|
|
@ -453,3 +453,32 @@ void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
|||
int32_t le24toh (uint8_t data[3]) {
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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);
|
|
@ -1482,3 +1482,26 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
|
|||
*size = numBits;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,5 +49,6 @@ int IOdemodFSK(uint8_t *dest, size_t size);
|
|||
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
|
||||
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 VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bit,size_t id_bits_size);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -96,6 +96,8 @@ typedef struct{
|
|||
#define CMD_ASK_SIM_TAG 0x021F
|
||||
#define CMD_PSK_SIM_TAG 0x0220
|
||||
#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 */
|
||||
|
||||
|
@ -135,6 +137,9 @@ typedef struct{
|
|||
#define CMD_READER_ICLASS_REPLAY 0x0395
|
||||
#define CMD_ICLASS_ISO14443A_WRITE 0x0397
|
||||
#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
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue