1
0
mirror of https://github.com/Proxmark/proxmark3.git synced 2025-03-12 04:35:36 -07:00

'lf hitag writer': add Hitag2 password auth

* (PRs 233, 303, 304 by @ViRb3 on https://github.com/RfidResearchGroup/proxmark3)
* replace byte_t by uint8_t
* note that Hitag1 commands are not yet available
* whitespace fixes
* #define Hitag2 commands
* whitespace
* add EOF wait time
* add powerup wait time
This commit is contained in:
pwpiwi 2019-08-22 07:54:55 +02:00 committed by GitHub
parent 0b4efbdef2
commit f2dbf3d2aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1026 additions and 914 deletions

@ -16,7 +16,6 @@
#include <stddef.h>
#include "common.h"
#include "usb_cmd.h"
#include "hitag2.h"
#include "hitagS.h"
#include "mifare.h"
#include "../common/crc32.h"

File diff suppressed because it is too large Load Diff

@ -16,9 +16,9 @@
#include <stdbool.h>
#include "hitag.h"
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
void WriterHitag(hitag_function htf, hitag_data* htd, int page);
extern void SnoopHitag(uint32_t type);
extern void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data);
extern void ReaderHitag(hitag_function htf, hitag_data* htd);
extern void WriterHitag(hitag_function htf, hitag_data* htd, int page);
#endif

@ -26,18 +26,6 @@
#define CRC_PRESET 0xFF
#define CRC_POLYNOM 0x1D
#define u8 uint8_t
#define u32 uint32_t
#define u64 uint64_t
#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8))
#define rev32(x) (rev16(x)+(rev16(x>>16)<<16))
#define rev64(x) (rev32(x)+(rev32(x>>32)<<32))
#define bit(x,n) (((x)>>(n))&1)
#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1)
#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
static bool bQuiet;
static bool bSuccessful;
static struct hitagS_tag tag;
@ -57,17 +45,17 @@ size_t blocknr;
bool end=false;
// Single bit Hitag2 functions:
#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001
static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
#define uf20bs u32
#define uf20bs uint32_t
static u32 f20(const u64 x) {
u32 i5;
static uint32_t f20(const uint64_t x) {
uint32_t i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
@ -77,8 +65,19 @@ static u32 f20(const u64 x) {
return (ht2_f5c >> i5) & 1;
}
static u64 hitag2_round(u64 *state) {
u64 x = *state;
static uint64_t hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
uint32_t i;
uint64_t x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (uint64_t) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
static uint64_t hitag2_round(uint64_t *state) {
uint64_t x = *state;
x = (x >> 1)
+ ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8)
@ -89,20 +88,12 @@ static u64 hitag2_round(u64 *state) {
*state = x;
return f20(x);
}
static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) {
u32 i;
u64 x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
static u32 hitag2_byte(u64 *x) {
u32 i, c;
static uint32_t hitag2_byte(uint64_t *x) {
uint32_t i, c;
for (i = 0, c = 0; i < 8; i++)
c += (u32) hitag2_round(x) << (i ^ 7);
c += (uint32_t) hitag2_round(x) << (i ^ 7);
return c;
}
@ -858,7 +849,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
byte_t rx_air[HITAG_FRAME_LEN];
byte_t page;
int i;
u64 state;
uint64_t state;
unsigned char crc;
// Copy the (original) received frame how it is send over the air
@ -956,8 +947,8 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
//challenge message received
Dbprintf("Challenge for UID: %X", temp_uid);
temp2++;
state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]),
rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])));
state = hitag2_init(REV64(tag.key), REV32(tag.pages[0][0]),
REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])));
Dbprintf(
",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
@ -1216,7 +1207,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
unsigned char uid[32];
byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00;
unsigned char crc;
u64 state;
uint64_t state;
byte_t auth_ks[4];
byte_t conf_pages[3];
memcpy(rx_air, rx, nbytes(rxlen));
@ -1356,11 +1347,11 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
*txlen = 64;
if(end!=true){
if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY
state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
state = hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
/*
Dbprintf("key: %02X %02X\n\n", key, rev64(key));
Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, rev32(tag.uid));
Dbprintf("rnd: %02X %02X\n\n", rnd, rev32(rnd));
Dbprintf("key: %02X %02X\n\n", key, REV64(key));
Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, REV32(tag.uid));
Dbprintf("rnd: %02X %02X\n\n", rnd, REV32(rnd));
*/
for (i = 0; i < 4; i++) {
auth_ks[i] = hitag2_byte(&state) ^ 0xff;
@ -1404,7 +1395,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr
pwdl0=0;
pwdl1=0;
if(htf==02 || htf==04) { //RHTS_KEY //WHTS_KEY
state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
state = hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
for (i = 0; i < 5; i++) {
hitag2_byte(&state);
}

@ -17,15 +17,21 @@
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
#define LED_RED 1
#define LED_RED 1
#define LED_ORANGE 2
#define LED_GREEN 4
#define LED_RED2 8
#define BUTTON_HOLD 1
#define BUTTON_NO_CLICK 0
#define BUTTON_SINGLE_CLICK -1
#define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99
#define LED_GREEN 4
#define LED_RED2 8
#define BUTTON_HOLD 1
#define BUTTON_NO_CLICK 0
#define BUTTON_SINGLE_CLICK -1
#define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99
#define REV8(x) ((((x)>>7)&1)|((((x)>>6)&1)<<1)|((((x)>>5)&1)<<2)|((((x)>>4)&1)<<3)|((((x)>>3)&1)<<4)|((((x)>>2)&1)<<5)|((((x)>>1)&1)<<6)|(((x)&1)<<7))
#define REV16(x) (REV8(x) | (REV8 (x >> 8) << 8))
#define REV32(x) (REV16(x) | (REV16(x >> 16) << 16))
#define REV64(x) (REV32(x) | (REV32(x >> 32) << 32))
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits);

@ -22,15 +22,13 @@
#include "hitag.h"
#include "cmdmain.h"
static int CmdHelp(const char *Cmd);
size_t nbytes(size_t nbits) {
return (nbits/8)+((nbits%8)>0);
static size_t nbytes(size_t nbits) {
return (nbits/8) + ((nbits%8)>0);
}
int CmdLFHitagList(const char *Cmd)
{
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
static int CmdLFHitagList(const char *Cmd) {
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
// Query for the actual size of the trace
UsbCommand response;
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false);
@ -45,7 +43,7 @@ int CmdLFHitagList(const char *Cmd)
got = p;
GetFromBigBuf(got, traceLen, 0, NULL, -1, false);
}
PrintAndLog("recorded activity (TraceLen = %d bytes):");
PrintAndLog(" ETU :nbits: who bytes");
PrintAndLog("---------+-----+----+-----------");
@ -57,11 +55,11 @@ int CmdLFHitagList(const char *Cmd)
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf = NULL;
if (len > FILE_PATH_SIZE)
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"wb")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
@ -71,7 +69,7 @@ int CmdLFHitagList(const char *Cmd)
}
for (;;) {
if(i > traceLen) { break; }
bool isResponse;
@ -95,7 +93,7 @@ int CmdLFHitagList(const char *Cmd)
int len = nbytes(bits);
if (len > 100) {
break;
break;
}
if (i + len > traceLen) { break;}
@ -104,7 +102,7 @@ int CmdLFHitagList(const char *Cmd)
int fillupBits = 8 - (bits % 8);
byte_t framefilled[bits+fillupBits];
byte_t* ff = framefilled;
int response_bit[200] = {0};
int z = 0;
for (int y = 0; y < len; y++) {
@ -133,12 +131,12 @@ int CmdLFHitagList(const char *Cmd)
char line[1000] = "";
for (j = 0; j < len; j++) {
//if((parityBits >> (len - j - 1)) & 0x01) {
if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
sprintf(line+(j*4), "%02x! ", frame[j]);
} else {
sprintf(line+(j*4), "%02x ", frame[j]);
}
//if((parityBits >> (len - j - 1)) & 0x01) {
if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
sprintf(line+(j*4), "%02x! ", frame[j]);
} else {
sprintf(line+(j*4), "%02x ", frame[j]);
}
}
PrintAndLog(" +%7d: %3d: %s %s",
@ -154,11 +152,11 @@ int CmdLFHitagList(const char *Cmd)
(isResponse ? "TAG" : " "),
line);
}
prev = timestamp;
i += (len + 9);
}
if (pf) {
fclose(pf);
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
@ -168,22 +166,24 @@ int CmdLFHitagList(const char *Cmd)
return 0;
}
int CmdLFHitagSnoop(const char *Cmd) {
UsbCommand c = {CMD_SNOOP_HITAG};
SendCommand(&c);
return 0;
static int CmdLFHitagSnoop(const char *Cmd) {
UsbCommand c = {CMD_SNOOP_HITAG};
SendCommand(&c);
return 0;
}
int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG};
static int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG};
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
@ -199,56 +199,114 @@ int CmdLFHitagSim(const char *Cmd) {
} else {
tag_mem_supplied = false;
}
// Does the tag comes with memory
c.arg[0] = (uint32_t)tag_mem_supplied;
SendCommand(&c);
return 0;
SendCommand(&c);
return 0;
}
int CmdLFHitagReader(const char *Cmd) {
UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}};
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd,0,0,10);
static bool getHitagUid(uint32_t *uid) {
// ToDo: this is for Hitag2 only (??)
UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY}};
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return false;
}
if (resp.arg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID");
return false;
}
if (uid)
*uid = bytes_to_num(resp.d.asBytes, 4);
return true;
}
static int CmdLFHitagInfo(const char *Cmd) {
char ctmp = param_getchar(Cmd, 0);
if (ctmp != '\0') {
PrintAndLog("Usage: lf hitag info [h]");
PrintAndLog("Options:");
PrintAndLog(" h This help");
PrintAndLog("Examples:");
PrintAndLog(" lf hitag info");
return 0;
}
// read UID
uint32_t uid = 0;
if (getHitagUid(&uid) == false)
return 1;
PrintAndLogEx(SUCCESS, "UID: %08X", uid);
// how to detemine Hitag types?
// read block3, get configuration byte.
// PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!"));
// common configurations.
// printHitagConfiguration(0x06);
//printHitagConfiguration( 0x0E );
//printHitagConfiguration( 0x02 );
//printHitagConfiguration( 0x00 );
//printHitagConfiguration( 0x04 );
return 0;
}
int CmdLFHitagReader(const char *Cmd) {
UsbCommand c = {CMD_READER_HITAG};
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd, 0, 0, 10);
switch (htf) {
case 01: { //RHTSF_CHALLENGE
c = (UsbCommand){ CMD_READ_HITAG_S };
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage
c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode
} break;
case 02: { //RHTSF_KEY
c = (UsbCommand){ CMD_READ_HITAG_S };
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage
c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode
} break;
case 03: { //RHTSF_CHALLENGE BLOCK
c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage
c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode
} break;
case 04: { //RHTSF_KEY BLOCK
c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage
c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode
} break;
case RHT2F_PASSWORD: {
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password);
} break;
case RHT2F_AUTHENTICATE: {
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
} break;
case RHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
// num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
// num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
} break;
case RHT2F_TEST_AUTH_ATTEMPTS: {
// No additional parameters needed
@ -261,19 +319,20 @@ int CmdLFHitagReader(const char *Cmd) {
PrintAndLog("");
PrintAndLog("Usage: hitag reader <Reader Function #>");
PrintAndLog("Reader Functions:");
PrintAndLog(" HitagS (0*)");
PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" Hitag2 (2*)");
PrintAndLog(" 21 <password> (password mode)");
PrintAndLog(" 22 <nr> <ar> (authentication)");
PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
PrintAndLog(" 25 (test recorded authentications)");
PrintAndLog(" 26 just read UID");
PrintAndLog(" HitagS (0*):");
PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
PrintAndLog(" Hitag1 (1*):");
PrintAndLog(" (not yet implemented)");
PrintAndLog(" Hitag2 (2*):");
PrintAndLog(" 21 <password> (password mode)");
PrintAndLog(" 22 <nr> <ar> (authentication)");
PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
PrintAndLog(" 25 (test recorded authentications)");
PrintAndLog(" 26 just read UID");
return 1;
} break;
}
@ -286,13 +345,19 @@ int CmdLFHitagReader(const char *Cmd) {
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
// Check the return status, stored in the first argument
if (resp.arg[0] == false) return 1;
if (resp.arg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
return 1;
}
uint32_t id = bytes_to_num(resp.d.asBytes,4);
if (htf == RHT2F_UID_ONLY){
PrintAndLog("Valid Hitag2 tag found - UID: %08x",id);
} else {
@ -312,12 +377,11 @@ int CmdLFHitagReader(const char *Cmd) {
PrintAndLog("Succesfully saved tag memory to [%s]",filename);
}
return 0;
}
int CmdLFHitagSimS(const char *Cmd) {
static int CmdLFHitagSimS(const char *Cmd) {
UsbCommand c = { CMD_SIMULATE_HITAG_S };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
@ -350,7 +414,8 @@ int CmdLFHitagSimS(const char *Cmd) {
return 0;
}
int CmdLFHitagCheckChallenges(const char *Cmd) {
static int CmdLFHitagCheckChallenges(const char *Cmd) {
UsbCommand c = { CMD_TEST_HITAGS_TRACES };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
@ -358,7 +423,7 @@ int CmdLFHitagCheckChallenges(const char *Cmd) {
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
@ -369,87 +434,101 @@ int CmdLFHitagCheckChallenges(const char *Cmd) {
PrintAndLog("Error: File reading error");
fclose(pf);
return 1;
}
}
fclose(pf);
} else {
file_given = false;
}
//file with all the challenges to try
c.arg[0] = (uint32_t)file_given;
c.arg[1] = param_get64ex(Cmd,2,0,0); //get mode
SendCommand(&c);
return 0;
SendCommand(&c);
return 0;
}
int CmdLFHitagWP(const char *Cmd) {
static int CmdLFHitagWriter(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S };
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd,0,0,10);
switch (htf) {
case 03: { //WHTSF_CHALLENGE
case WHTSF_CHALLENGE: {
num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
} break;
case 04:
case 24:
{ //WHTSF_KEY
case WHTSF_KEY:
case WHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data);
} break;
case WHT2F_PASSWORD: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 4, htd->pwd.password);
c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data);
} break;
default: {
PrintAndLog("Error: unkown writer function %d",htf);
PrintAndLog("Hitag writer functions");
PrintAndLog(" HitagS (0*)");
PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" Hitag2 (2*)");
PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" HitagS (0*):");
PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" (not yet implemented)");
PrintAndLog(" Hitag2 (2*):");
PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLog(" 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
return 1;
} break;
}
// Copy the hitag function into the first argument
c.arg[0] = htf;
// Send the command to the proxmark
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
// Check the return status, stored in the first argument
if (resp.arg[0] == false) return 1;
return 0;
// Send the command to the proxmark
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
// Check the return status, stored in the first argument
if (resp.arg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed");
return 1;
}
return 0;
}
static command_t CommandTable[] =
static int CmdHelp(const char *Cmd);
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" },
{"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" },
{"checkChallenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> <tagmode> test all challenges" }, {
NULL,NULL, 0, NULL }
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 0, "<outfile> List Hitag trace history"},
{"info", CmdLFHitagInfo, 0, "Tag information" },
{"reader", CmdLFHitagReader, 0, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 0, "Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 0, "Eavesdrop Hitag communication"},
{"writer", CmdLFHitagWriter, 0, "Act like a Hitag Writer" },
{"simS", CmdLFHitagSimS, 0, "Simulate HitagS transponder" },
{"checkChallenges", CmdLFHitagCheckChallenges, 0, "Test challenges from a file" },
{ NULL, NULL, 0, NULL }
};
int CmdLFHitag(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
static int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
int CmdLFHitag(const char *Cmd) {
CmdsParse(CommandTable, Cmd);
return 0;
}

@ -11,11 +11,7 @@
#ifndef CMDLFHITAG_H__
#define CMDLFHITAG_H__
int CmdLFHitag(const char *Cmd);
int CmdLFHitagList(const char *Cmd);
int CmdLFHitagSnoop(const char *Cmd);
int CmdLFHitagSim(const char *Cmd);
int CmdLFHitagReader(const char *Cmd);
extern int CmdLFHitag(const char *Cmd);
extern int CmdLFHitagReader(const char *Cmd);
#endif

@ -236,6 +236,26 @@ NXP/Philips CUSTOM COMMANDS
#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
// HITAG1 commands
#define HITAG1_SET_CCNEW 0xC2 // left 5 bits only
#define HITAG1_READ_ID 0x00 // not a real command, consists of 5 bits length, <length> bits partial SN, 8 bits CRC
#define HITAG1_SELECT 0x00 // left 5 bits only, followed by 32 bits SN and 8 bits CRC
#define HITAG1_WRPPAGE 0x80 // left 4 bits only, followed by 8 bits page and 8 bits CRC
#define HITAG1_WRPBLK 0x90 // left 4 bits only, followed by 8 bits block and 8 bits CRC
#define HITAG1_WRCPAGE 0xA0 // left 4 bits only, followed by 8 bits page or key information and 8 bits CRC
#define HITAG1_WRCBLK 0xB0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
#define HITAG1_RDPPAGE 0xC0 // left 4 bits only, followed by 8 bits page and 8 bits CRC
#define HITAG1_RDPBLK 0xD0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
#define HITAG1_RDCPAGE 0xE0 // left 4 bits only, followed by 8 bits page and 8 bits CRC
#define HITAG1_RDCBLK 0xF0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
#define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC
// HITAG2 commands
#define HITAG2_START_AUTH 0xC0 // left 5 bits only
#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_HALT 0x00 // left 5 bits only
#define ISO_14443A 0
#define ICLASS 1

@ -31,6 +31,7 @@ typedef enum {
WHT2F_CRYPTO = 24,
RHT2F_TEST_AUTH_ATTEMPTS = 25,
RHT2F_UID_ONLY = 26,
WHT2F_PASSWORD = 27,
} hitag_function;
typedef struct {