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 //----------------------------------------------------------------------------- 
  15 #include "proxmark3.h" 
  17 #include "cmdparser.h" 
  25 static int CmdHelp(const char *Cmd
); 
  27 size_t nbytes(size_t nbits
) { 
  28         return (nbits
/8)+((nbits%8
)>0); 
  31 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); 
  37         WaitForResponse(CMD_ACK
, &response
); 
  38         uint16_t traceLen 
= response
.arg
[2]; 
  39         if (traceLen 
> USB_CMD_DATA_SIZE
) { 
  40                 uint8_t *p 
= realloc(got
, traceLen
); 
  42                         PrintAndLog("Cannot allocate memory for trace"); 
  47                 GetFromBigBuf(got
, traceLen
, 0); 
  48                 WaitForResponse(CMD_ACK
,NULL
); 
  51         PrintAndLog("recorded activity (TraceLen = %d bytes):"); 
  52         PrintAndLog(" ETU     :nbits: who bytes"); 
  53         PrintAndLog("---------+-----+----+-----------"); 
  57         int len 
= strlen(Cmd
); 
  59         char filename
[FILE_PATH_SIZE
]  = { 0x00 }; 
  62         if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
  63         memcpy(filename
, Cmd
, len
); 
  65         if (strlen(filename
) > 0) { 
  66                 f 
= fopen(filename
,"wb"); 
  68                         PrintAndLog("Error: Could not open file [%s]",filename
); 
  75                 if(i 
>= traceLen
) { break; } 
  78                 int timestamp 
= *((uint32_t *)(got
+i
)); 
  79                 if (timestamp 
& 0x80000000) { 
  80                         timestamp 
&= 0x7fffffff; 
  86                 int parityBits 
= *((uint32_t *)(got
+i
+4)); 
  87                 // 4 bytes of additional information... 
  88                 // maximum of 32 additional parity bit information 
  91                 // at each quarter bit period we can send power level (16 levels) 
  92                 // or each half bit period in 256 levels. 
  95                 int len 
= nbytes(got
[i
+8]); 
 100                 if (i 
+ len 
> traceLen
) { break;} 
 102                 uint8_t *frame 
= (got
+i
+9); 
 104                 // Break and stick with current result if buffer was not completely full 
 105                 if (frame
[0] == 0x44 && frame
[1] == 0x44 && frame
[3] == 0x44) { break; } 
 107                 char line
[1000] = ""; 
 109                 for (j 
= 0; j 
< len
; j
++) { 
 110                   int oddparity 
= 0x01; 
 114                         oddparity 
^= (((frame
[j
] & 0xFF) >> k
) & 0x01); 
 117                   //if((parityBits >> (len - j - 1)) & 0x01) { 
 118                   if (isResponse 
&& (oddparity 
!= ((parityBits 
>> (len 
- j 
- 1)) & 0x01))) { 
 119                         sprintf(line
+(j
*4), "%02x!  ", frame
[j
]); 
 122                         sprintf(line
+(j
*4), "%02x   ", frame
[j
]); 
 126                 PrintAndLog(" +%7d:  %3d: %s %s", 
 127                         (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
 129                         (isResponse 
? "TAG" : "   "), 
 133                         fprintf(f
," +%7d:  %3d: %s %s\n", 
 134                                 (prev 
< 0 ? 0 : (timestamp 
- prev
)), 
 136                                 (isResponse 
? "TAG" : "   "), 
 146                 PrintAndLog("Recorded activity succesfully written to file: %s", filename
); 
 153 int CmdLFHitagSnoop(const char *Cmd
) { 
 154         UsbCommand c 
= {CMD_SNOOP_HITAG
}; 
 155         clearCommandBuffer(); 
 160 int CmdLFHitagSim(const char *Cmd
) { 
 162         UsbCommand c 
= {CMD_SIMULATE_HITAG
}; 
 163         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 165         bool tag_mem_supplied
; 
 167         int len 
= strlen(Cmd
); 
 168         if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
 169         memcpy(filename
, Cmd
, len
); 
 171         if (strlen(filename
) > 0) { 
 172                 f 
= fopen(filename
,"rb+"); 
 174                         PrintAndLog("Error: Could not open file [%s]",filename
); 
 177                 tag_mem_supplied 
= true; 
 178                 size_t bytes_read 
= fread(c
.d
.asBytes
, 48, 1, f
); 
 179                 if ( bytes_read 
== 0) { 
 180                         PrintAndLog("Error: File reading error"); 
 186                 tag_mem_supplied 
= false; 
 189         // Does the tag comes with memory 
 190         c
.arg
[0] = (uint32_t)tag_mem_supplied
; 
 191         clearCommandBuffer(); 
 196 int CmdLFHitagReader(const char *Cmd
) { 
 198         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)}}; 
 199         hitag_data
* htd 
= (hitag_data
*)c
.d
.asBytes
; 
 200         hitag_function htf 
= param_get32ex(Cmd
,0,0,10); 
 203                 case 01: { //RHTSF_CHALLENGE 
 204                         c 
= (UsbCommand
){ CMD_READ_HITAG_S 
}; 
 205                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->auth
.NrAr
); 
 206                         num_to_bytes(param_get32ex(Cmd
,2,0,16),4,htd
->auth
.NrAr
+4); 
 208                 case 02: { //RHTSF_KEY 
 209                         c 
= (UsbCommand
){ CMD_READ_HITAG_S 
}; 
 210                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 212                 case RHT2F_PASSWORD
: { 
 213                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->pwd
.password
); 
 215                 case RHT2F_AUTHENTICATE
: { 
 216                         num_to_bytes(param_get32ex(Cmd
,1,0,16),4,htd
->auth
.NrAr
); 
 217                         num_to_bytes(param_get32ex(Cmd
,2,0,16),4,htd
->auth
.NrAr
+4); 
 220                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 222                 case RHT2F_TEST_AUTH_ATTEMPTS
: { 
 223                         // No additional parameters needed 
 225                 case RHT2F_UID_ONLY
: { 
 226                         // No additional parameters needed 
 229                         PrintAndLog("\nError: unkown reader function %d",htf
); 
 231                         PrintAndLog("Usage: hitag reader <Reader Function #>"); 
 232                         PrintAndLog("Reader Functions:"); 
 233                         PrintAndLog(" HitagS (0*)"); 
 234                         PrintAndLog("  01 <nr> <ar> (Challenge) read all pages from a Hitag S tag"); 
 235                         PrintAndLog("  02 <key> (set to 0 if no authentication is needed) read all pages from a Hitag S tag"); 
 236                         PrintAndLog(" Hitag1 (1*)"); 
 237                         PrintAndLog(" Hitag2 (2*)"); 
 238                         PrintAndLog("  21 <password> (password mode)"); 
 239                         PrintAndLog("  22 <nr> <ar> (authentication)"); 
 240                         PrintAndLog("  23 <key> (authentication) key is in format: ISK high + ISK low"); 
 241                         PrintAndLog("  25 (test recorded authentications)"); 
 242                         PrintAndLog("  26 just read UID"); 
 247         // Copy the hitag2 function into the first argument 
 249         clearCommandBuffer(); 
 252         WaitForResponse(CMD_ACK
,&resp
); 
 254         // Check the return status, stored in the first argument 
 255         if (resp
.arg
[0] == false) return 1; 
 257         uint32_t id 
= bytes_to_num(resp
.d
.asBytes
,4); 
 259         if (htf 
== RHT2F_UID_ONLY
){ 
 260                 PrintAndLog("Valid Hitag2 tag found - UID: %08x",id
); 
 262         char filename
[FILE_PATH_SIZE
]; 
 264         sprintf(filename
,"%08x_%04x.ht2",id
,(rand() & 0xffff)); 
 265         f 
= fopen(filename
,"wb"); 
 267                 PrintAndLog("Error: Could not open file [%s]",filename
); 
 271         // Write the 48 tag memory bytes to file and finalize 
 272         fwrite(resp
.d
.asBytes
, 1, 48, f
); 
 274         PrintAndLog("Succesfully saved tag memory to [%s]",filename
); 
 279 int CmdLFHitagSimS(const char *Cmd
) { 
 280         UsbCommand c 
= { CMD_SIMULATE_HITAG_S 
}; 
 281         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 283         bool tag_mem_supplied
; 
 284         int len 
= strlen(Cmd
); 
 285         if (len 
> FILE_PATH_SIZE
) 
 286                 len 
= FILE_PATH_SIZE
; 
 287         memcpy(filename
, Cmd
, len
); 
 289         if (strlen(filename
) > 0) { 
 290                 f 
= fopen(filename
, "rb+"); 
 292                         PrintAndLog("Error: Could not open file [%s]", filename
); 
 295                 tag_mem_supplied 
= true; 
 296                 size_t bytes_read 
= fread(c
.d
.asBytes
, 4*64, 1, f
); 
 297                 if ( bytes_read 
== 0) { 
 298                         PrintAndLog("Error: File reading error"); 
 304                 tag_mem_supplied 
= false; 
 307         // Does the tag comes with memory 
 308         c
.arg
[0] = (uint32_t) tag_mem_supplied
; 
 309         clearCommandBuffer(); 
 314 int CmdLFHitagCheckChallenges(const char *Cmd
) { 
 315         UsbCommand c 
= { CMD_TEST_HITAGS_TRACES 
}; 
 316         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 319         int len 
= strlen(Cmd
); 
 320         if (len 
> FILE_PATH_SIZE
) len 
= FILE_PATH_SIZE
; 
 321         memcpy(filename
, Cmd
, len
); 
 323         if (strlen(filename
) > 0) { 
 324                 f 
= fopen(filename
,"rb+"); 
 326                         PrintAndLog("Error: Could not open file [%s]", filename
); 
 330                 size_t bytes_read 
= fread(c
.d
.asBytes
, 8*60, 1, f
); 
 331                 if ( bytes_read 
== 0) { 
 332                         PrintAndLog("Error: File reading error"); 
 341         //file with all the challenges to try 
 342         c
.arg
[0] = (uint32_t)file_given
; 
 343         clearCommandBuffer(); 
 348 int CmdLFHitagWP(const char *Cmd
) { 
 349         UsbCommand c 
= { CMD_WR_HITAG_S 
}; 
 350         hitag_data
* htd 
= (hitag_data
*)c
.d
.asBytes
; 
 351         hitag_function htf 
= param_get32ex(Cmd
,0,0,10); 
 353                 case 03: { //WHTSF_CHALLENGE 
 354                         num_to_bytes(param_get64ex(Cmd
,1,0,16),8,htd
->auth
.NrAr
); 
 355                         c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10); 
 356                         num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->auth
.data
); 
 358                 case 04: { //WHTSF_KEY 
 359                         num_to_bytes(param_get64ex(Cmd
,1,0,16),6,htd
->crypto
.key
); 
 360                         c
.arg
[2]= param_get32ex(Cmd
, 2, 0, 10); 
 361                         num_to_bytes(param_get32ex(Cmd
,3,0,16),4,htd
->crypto
.data
); 
 365                         PrintAndLog("Error: unkown writer function %d",htf
); 
 366                         PrintAndLog("Hitag writer functions"); 
 367                         PrintAndLog(" HitagS (0*)"); 
 368                         PrintAndLog("  03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag"); 
 369                         PrintAndLog("  04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag"); 
 370                         PrintAndLog(" Hitag1 (1*)"); 
 371                         PrintAndLog(" Hitag2 (2*)"); 
 375         // Copy the hitag function into the first argument 
 378         clearCommandBuffer(); 
 381         WaitForResponse(CMD_ACK
,&resp
); 
 383         // Check the return status, stored in the first argument 
 384         if (resp
.arg
[0] == false) return 1; 
 388 static command_t CommandTable
[] =  
 390         {"help",    CmdHelp
,           1, "This help"}, 
 391         {"list",    CmdLFHitagList
,    1, "<outfile> List Hitag trace history"}, 
 392         {"reader",  CmdLFHitagReader
,  1, "Act like a Hitag Reader"}, 
 393         {"sim",     CmdLFHitagSim
,     1, "<infile> Simulate Hitag transponder"}, 
 394         {"snoop",   CmdLFHitagSnoop
,   1, "Eavesdrop Hitag communication"}, 
 395   {"writer",            CmdLFHitagWP
,      1, "Act like a Hitag Writer" }, 
 396   {"simS",              CmdLFHitagSimS
,    1, "<hitagS.hts> Simulate HitagS transponder" },  
 397   {"checkChallenges",   CmdLFHitagCheckChallenges
,   1, "<challenges.cc> test all challenges" }, { 
 401 int CmdLFHitag(const char *Cmd
) { 
 402         clearCommandBuffer(); 
 403         CmdsParse(CommandTable
, Cmd
); 
 407 int CmdHelp(const char *Cmd
) { 
 408         CmdsHelp(CommandTable
);