1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2012 Roel Verdult 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // Low frequency Hitag support 
   9 //----------------------------------------------------------------------------- 
  14 #include "proxmark3.h" 
  16 #include "cmdparser.h" 
  24 static int CmdHelp(const char *Cmd
); 
  26 size_t nbytes(size_t nbits
) { 
  27         return (nbits
/8)+((nbits%8
)>0); 
  30 int CmdLFHitagList(const char *Cmd
) 
  32         uint8_t *got 
= malloc(USB_CMD_DATA_SIZE
); 
  34         // Query for the actual size of the trace 
  36         GetFromBigBuf(got
, USB_CMD_DATA_SIZE
, 0, &response
, -1, false); 
  37         uint16_t traceLen 
= response
.arg
[2]; 
  38         if (traceLen 
> USB_CMD_DATA_SIZE
) { 
  39                 uint8_t *p 
= realloc(got
, traceLen
); 
  41                         PrintAndLog("Cannot allocate memory for trace"); 
  46                 GetFromBigBuf(got
, traceLen
, 0, NULL
, -1, false); 
  49         PrintAndLog("recorded activity (TraceLen = %d bytes):"); 
  50         PrintAndLog(" ETU     :nbits: who bytes"); 
  51         PrintAndLog("---------+-----+----+-----------"); 
  55         int len 
= strlen(Cmd
); 
  57         char filename
[FILE_PATH_SIZE
]  = { 0x00 }; 
  60         if (len 
> FILE_PATH_SIZE
)  
  62         memcpy(filename
, Cmd
, len
); 
  64         if (strlen(filename
) > 0) { 
  65                 if ((pf 
= fopen(filename
,"wb")) == NULL
) { 
  66                         PrintAndLog("Error: Could not open file [%s]",filename
); 
  73                 if(i 
> traceLen
) { break; } 
  76                 int timestamp 
= *((uint32_t *)(got
+i
)); 
  77                 if (timestamp 
& 0x80000000) { 
  78                         timestamp 
&= 0x7fffffff; 
  84                 int parityBits 
= *((uint32_t *)(got
+i
+4)); 
  85                 // 4 bytes of additional information... 
  86                 // maximum of 32 additional parity bit information 
  89                 // at each quarter bit period we can send power level (16 levels) 
  90                 // or each half bit period in 256 levels. 
  93                 int len 
= nbytes(got
[i
+8]); 
  98                 if (i 
+ len 
> traceLen
) { break;} 
 100                 uint8_t *frame 
= (got
+i
+9); 
 102                 // Break and stick with current result if buffer was not completely full 
 103                 if (frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
 105                 char line
[1000] = ""; 
 107                 for (j 
= 0; j 
< len
; j
++) { 
 109                   //if((parityBits >> (len - j - 1)) & 0x01) { 
 110                   if (isResponse 
&& (oddparity8(frame
[j
]) != ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
 111                         sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
 114                         sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
 118                 PrintAndLog(" +%7d:  %3d: %s %s", 
 119                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
 121                         (isResponse 
? "TAG" : "   "), 
 125                         fprintf(pf
," +%7d:  %3d: %s %s\n", 
 126                                 (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
 128                                 (isResponse 
? "TAG" : "   "), 
 138                 PrintAndLog("Recorded activity succesfully written to file: %s", filename
); 
 145 int CmdLFHitagSnoop(const char *Cmd
) { 
 146   UsbCommand c 
= {CMD_SNOOP_HITAG
}; 
 151 int CmdLFHitagSim(const char *Cmd
) { 
 153   UsbCommand c 
= {CMD_SIMULATE_HITAG
}; 
 154         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 156         bool tag_mem_supplied
; 
 157         int len 
= strlen(Cmd
); 
 158         if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
 159         memcpy(filename
, Cmd
, len
); 
 161         if (strlen(filename
) > 0) { 
 162                 if ((pf 
= fopen(filename
,"rb+")) == NULL
) { 
 163                         PrintAndLog("Error: Could not open file [%s]",filename
); 
 166                 tag_mem_supplied 
= true; 
 167                 if (fread(c
.d
.asBytes
,48,1,pf
) == 0) { 
 168       PrintAndLog("Error: File reading error"); 
 174                 tag_mem_supplied 
= false; 
 177         // Does the tag comes with memory 
 178         c
.arg
[0] = (uint32_t)tag_mem_supplied
; 
 184 int CmdLFHitagReader(const char *Cmd
) { 
 185         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)}}; 
 186         hitag_data
* htd 
= (hitag_data
*)c
.d
.asBytes
; 
 187         hitag_function htf 
= param_get32ex(Cmd
,0,0,10); 
 190                 case 01: { //RHTSF_CHALLENGE 
 191                         c 
= (UsbCommand
){ CMD_READ_HITAG_S 
}; 
 192                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->auth
.NrAr
); 
 193                         num_to_bytes(param_get32ex(Cmd
,2,0,16),4,htd
->auth
.NrAr
+4); 
 195                 case 02: { //RHTSF_KEY 
 196                         c 
= (UsbCommand
){ CMD_READ_HITAG_S 
}; 
 197                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 199                 case RHT2F_PASSWORD
: { 
 200                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->pwd
.password
); 
 202                 case RHT2F_AUTHENTICATE
: { 
 203                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->auth
.NrAr
); 
 204                         num_to_bytes(param_get32ex(Cmd
,2,0,16),4,htd
->auth
.NrAr
+4); 
 207                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 208                         //                      num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4); 
 210                 case RHT2F_TEST_AUTH_ATTEMPTS
: { 
 211                         // No additional parameters needed 
 213                 case RHT2F_UID_ONLY
: { 
 214                         // No additional parameters needed 
 217                         PrintAndLog("\nError: unkown reader function %d",htf
); 
 219                         PrintAndLog("Usage: hitag reader <Reader Function #>"); 
 220                         PrintAndLog("Reader Functions:"); 
 221                         PrintAndLog(" HitagS (0*)"); 
 222                         PrintAndLog("  01 <nr> <ar> (Challenge) read all pages from a Hitag S tag"); 
 223                         PrintAndLog("  02 <key> (set to 0 if no authentication is needed) read all pages from a Hitag S tag"); 
 224                         PrintAndLog(" Hitag1 (1*)"); 
 225                         PrintAndLog(" Hitag2 (2*)"); 
 226                         PrintAndLog("  21 <password> (password mode)"); 
 227                         PrintAndLog("  22 <nr> <ar> (authentication)"); 
 228                         PrintAndLog("  23 <key> (authentication) key is in format: ISK high + ISK low"); 
 229                         PrintAndLog("  25 (test recorded authentications)"); 
 230                         PrintAndLog("  26 just read UID"); 
 235         // Copy the hitag2 function into the first argument 
 238         // Send the command to the proxmark 
 239         clearCommandBuffer(); 
 243         WaitForResponse(CMD_ACK
,&resp
); 
 245         // Check the return status, stored in the first argument 
 246         if (resp
.arg
[0] == false) return 1; 
 248         uint32_t id 
= bytes_to_num(resp
.d
.asBytes
,4); 
 250         if (htf 
== RHT2F_UID_ONLY
){ 
 251                 PrintAndLog("Valid Hitag2 tag found - UID: %08x",id
); 
 256                 sprintf(filename
,"%08x_%04x.ht2",id
,(rand() & 0xffff)); 
 257                 if ((pf 
= fopen(filename
,"wb")) == NULL
) { 
 258                   PrintAndLog("Error: Could not open file [%s]",filename
); 
 262                 // Write the 48 tag memory bytes to file and finalize 
 263                 fwrite(resp
.d
.asBytes
,1,48,pf
); 
 266                 PrintAndLog("Succesfully saved tag memory to [%s]",filename
); 
 274 int CmdLFHitagSimS(const char *Cmd
) { 
 275         UsbCommand c 
= { CMD_SIMULATE_HITAG_S 
}; 
 276         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 278         bool tag_mem_supplied
; 
 279         int len 
= strlen(Cmd
); 
 280         if (len 
> FILE_PATH_SIZE
) 
 281                 len 
= FILE_PATH_SIZE
; 
 282         memcpy(filename
, Cmd
, len
); 
 284         if (strlen(filename
) > 0) { 
 285                 if ((pf 
= fopen(filename
, "rb+")) == NULL
) { 
 286                         PrintAndLog("Error: Could not open file [%s]", filename
); 
 289                 tag_mem_supplied 
= true; 
 290                 if (fread(c
.d
.asBytes
, 4*64, 1, pf
) == 0) { 
 291                         PrintAndLog("Error: File reading error"); 
 297                 tag_mem_supplied 
= false; 
 300         // Does the tag comes with memory 
 301         c
.arg
[0] = (uint32_t) tag_mem_supplied
; 
 307 int CmdLFHitagCheckChallenges(const char *Cmd
) { 
 308         UsbCommand c 
= { CMD_TEST_HITAGS_TRACES 
}; 
 309         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 312         int len 
= strlen(Cmd
); 
 313         if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
 314         memcpy(filename
, Cmd
, len
); 
 316         if (strlen(filename
) > 0) { 
 317                 if ((pf 
= fopen(filename
,"rb+")) == NULL
) { 
 318                         PrintAndLog("Error: Could not open file [%s]",filename
); 
 322                 if (fread(c
.d
.asBytes
,8*60,1,pf
) == 0) { 
 323       PrintAndLog("Error: File reading error"); 
 332         //file with all the challenges to try 
 333         c
.arg
[0] = (uint32_t)file_given
; 
 340 int CmdLFHitagWP(const char *Cmd
) { 
 341         UsbCommand c 
= { CMD_WR_HITAG_S 
}; 
 342         hitag_data
* htd 
= (hitag_data
*)c
.d
.asBytes
; 
 343         hitag_function htf 
= param_get32ex(Cmd
,0,0,10); 
 345                 case 03: { //WHTSF_CHALLENGE 
 346                         num_to_bytes(param_get64ex(Cmd
,1,0,16),8,htd
->auth
.NrAr
); 
 347                         c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10); 
 348                         num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->auth
.data
); 
 353                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 354                         c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10); 
 355                         num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->crypto
.data
); 
 359                         PrintAndLog("Error: unkown writer function %d",htf
); 
 360                         PrintAndLog("Hitag writer functions"); 
 361                         PrintAndLog(" HitagS (0*)"); 
 362                         PrintAndLog("  03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag"); 
 363                         PrintAndLog("  04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag"); 
 364                         PrintAndLog(" Hitag1 (1*)"); 
 365                         PrintAndLog(" Hitag2 (2*)"); 
 366                         PrintAndLog("  24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag"); 
 370         // Copy the hitag function into the first argument 
 373   // Send the command to the proxmark 
 377   WaitForResponse(CMD_ACK
,&resp
); 
 379   // Check the return status, stored in the first argument 
 380   if (resp
.arg
[0] == false) return 1; 
 385 static command_t CommandTable
[] =  
 387   {"help",              CmdHelp
,           1, "This help"}, 
 388   {"list",              CmdLFHitagList
,    1, "<outfile> List Hitag trace history"}, 
 389   {"reader",            CmdLFHitagReader
,  1, "Act like a Hitag Reader"}, 
 390   {"sim",               CmdLFHitagSim
,     1, "<infile> Simulate Hitag transponder"}, 
 391   {"snoop",             CmdLFHitagSnoop
,   1, "Eavesdrop Hitag communication"}, 
 392   {"writer",            CmdLFHitagWP
,      1, "Act like a Hitag Writer" }, 
 393   {"simS",              CmdLFHitagSimS
,    1, "<hitagS.hts> Simulate HitagS transponder" },  
 394   {"checkChallenges",   CmdLFHitagCheckChallenges
,   1, "<challenges.cc> test all challenges" }, { 
 398 int CmdLFHitag(const char *Cmd
) 
 400   CmdsParse(CommandTable
, Cmd
); 
 404 int CmdHelp(const char *Cmd
) 
 406   CmdsHelp(CommandTable
);