]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhficlass.c
CHG: "hf mfu info" now always tries to read the NDEF CC. (was restricted to only...
[proxmark3-svn] / client / cmdhficlass.c
index 2d6a9beb99045c7cba945878462ac94b4de9f865..d6c791656806f2540797b0facc30478bc658738d 100644 (file)
@@ -29,6 +29,8 @@
 #include "loclass/ikeys.h"
 #include "loclass/elite_crack.h"
 #include "loclass/fileutils.h"
+#include "protocols.h"
+#include "usb_cmd.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -53,6 +55,21 @@ int CmdHFiClassSnoop(const char *Cmd)
        SendCommand(&c);
        return 0;
 }
+int usage_hf_iclass_sim()
+{
+       PrintAndLog("Usage:  hf iclass sim <option> [CSN]");
+       PrintAndLog("        options");
+       PrintAndLog("                0 <CSN> simulate the given CSN");
+       PrintAndLog("                1       simulate default CSN");
+       PrintAndLog("                2       Reader-attack, gather reader responses to extract elite key");
+       PrintAndLog("                3       Full simulation using emulator memory (see 'hf iclass eload')");
+       PrintAndLog("        example: hf iclass sim 0 031FEC8AF7FF12E0");
+       PrintAndLog("        example: hf iclass sim 2");
+       PrintAndLog("        example: hf iclass eload 'tagdump.bin'");
+       PrintAndLog("                 hf iclass sim 3");
+       return 0;
+}
+
 #define NUM_CSNS 15
 int CmdHFiClassSim(const char *Cmd)
 {
@@ -60,50 +77,31 @@ int CmdHFiClassSim(const char *Cmd)
        uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 
        if (strlen(Cmd)<1) {
-               PrintAndLog("Usage:  hf iclass sim [0 <CSN>] | x");
-               PrintAndLog("        options");
-               PrintAndLog("                0 <CSN> simulate the given CSN");
-               PrintAndLog("                1       simulate default CSN");
-               PrintAndLog("                2       iterate CSNs, gather MACs");
-               PrintAndLog("        sample: hf iclass sim 0 031FEC8AF7FF12E0");
-               PrintAndLog("        sample: hf iclass sim 2");
-               return 0;
+               return usage_hf_iclass_sim();
        }
-
-       simType = param_get8(Cmd, 0);
+       simType = param_get8ex(Cmd, 0, 0, 10);
 
        if(simType == 0)
        {
                if (param_gethex(Cmd, 1, CSN, 16)) {
                        PrintAndLog("A CSN should consist of 16 HEX symbols");
-                       return 1;
+                       return usage_hf_iclass_sim();
                }
-               PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
 
+               PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
        }
-       if(simType > 2)
+       if(simType > 3)
        {
                PrintAndLog("Undefined simptype %d", simType);
-               return 1;
+               return usage_hf_iclass_sim();
        }
-       uint8_t numberOfCSNs=0;
 
+       uint8_t numberOfCSNs=0;
        if(simType == 2)
        {
                UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
                UsbCommand resp = {0};
 
-               /*uint8_t csns[8 * NUM_CSNS] = {
-                        0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
-                        0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
-                        0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
-                        0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
-                        0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
-                        0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
-                        0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
-                        0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
-*/
-
                uint8_t csns[8*NUM_CSNS] = {
                        0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
                        0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
@@ -167,38 +165,47 @@ int CmdHFiClassSim(const char *Cmd)
        return 0;
 }
 
-int CmdHFiClassReader(const char *Cmd)
+int HFiClassReader(const char *Cmd, bool loop, bool verbose)
 {
-       UsbCommand c = {CMD_READER_ICLASS, {0}};
+       bool tagFound = false;
+       UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
+                                       FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
+       if (!loop) c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
        SendCommand(&c);
        UsbCommand resp;
        while(!ukbhit()){
                if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
-                       uint8_t isOK    = resp.arg[0] & 0xff;
+                       uint8_t readStatus    = resp.arg[0] & 0xff;
                        uint8_t * data  = resp.d.asBytes;
 
-                       PrintAndLog("isOk:%02x", isOK);
-                       if( isOK == 0){
+                       if (verbose)
+                       PrintAndLog("Readstatus:%02x", readStatus);
+                       if( readStatus == 0){
                                //Aborted
-                               PrintAndLog("Quitting...");
+                               if (verbose) PrintAndLog("Quitting...");
                                return 0;
                        }
-                       if(isOK > 0)
-                       {
+                       if( readStatus & FLAG_ICLASS_READER_CSN){
                                PrintAndLog("CSN: %s",sprint_hex(data,8));
+                               tagFound = true;
                        }
-                       if(isOK >= 1)
-                       {
-                               PrintAndLog("CC: %s",sprint_hex(data+8,8));
-                       }else{
-                               PrintAndLog("No CC obtained");
+                       if( readStatus & FLAG_ICLASS_READER_CC)  PrintAndLog("CC: %s",sprint_hex(data+16,8));
+                       if( readStatus & FLAG_ICLASS_READER_CONF){
+                               printIclassDumpInfo(data);
                        }
+                       if (tagFound && !loop) return 1;
                } else {
-                       PrintAndLog("Command execute timeout");
+                       if (verbose) PrintAndLog("Command execute timeout");
                }
+               if (!loop) break;
        }
-
        return 0;
+
+}
+
+int CmdHFiClassReader(const char *Cmd)
+{
+       return HFiClassReader(Cmd, true, true);
 }
 
 int CmdHFiClassReader_Replay(const char *Cmd)
@@ -272,7 +279,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
        uint8_t key_sel_p[8] = { 0 };
 
        UsbCommand c = {CMD_READER_ICLASS, {0}};
-       c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
+       c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
        SendCommand(&c);
 
 
@@ -287,7 +294,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
        uint8_t * data  = resp.d.asBytes;
 
        memcpy(CSN,data,8);
-       memcpy(CCNR,data+8,8);
+       memcpy(CCNR,data+16,8);
 
        PrintAndLog("isOk:%02x", isOK);
 
@@ -325,7 +332,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
        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,12,div_key, MAC);
+       doMAC(CCNR,div_key, MAC);
        printvar("MAC", MAC, 4);
 
        uint8_t iclass_data[32000] = {0};
@@ -351,7 +358,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
                        if(dataLength > 0)
                        {
                                PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
-                               memcpy(iclass_data, resp.d.asBytes,dataLength);
+                               memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
                                iclass_datalen += dataLength;
                        }else
                        {//Last transfer, datalength 0 means the dump is finished
@@ -367,6 +374,8 @@ int CmdHFiClassReader_Dump(const char *Cmd)
                                        snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
                                                         CSN[0],CSN[1],CSN[2],CSN[3],
                                                        CSN[4],CSN[5],CSN[6],CSN[7]);
+                                       //Place the div_key in block 3
+                                       memcpy(iclass_data+(3*8), div_key, 8);
                                        saveFile(filename,"bin",iclass_data, iclass_datalen );
                                }
                                //Aaaand we're finished
@@ -422,9 +431,12 @@ int CmdHFiClassELoad(const char *Cmd)
        fseek(f, 0, SEEK_SET);
 
        uint8_t *dump = malloc(fsize);
+
+
        size_t bytes_read = fread(dump, 1, fsize, f);
        fclose(f);
 
+       printIclassDumpInfo(dump);
        //Validate
 
        if (bytes_read < fsize)
@@ -450,6 +462,103 @@ int CmdHFiClassELoad(const char *Cmd)
        return 0;
 }
 
+int usage_hf_iclass_decrypt()
+{
+       PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
+       PrintAndLog("");
+       PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
+       PrintAndLog("in the working directory. The file should be 16 bytes binary data");
+       PrintAndLog("");
+       PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
+       PrintAndLog("");
+       PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
+       PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
+       PrintAndLog("which is defined by the configuration block.");
+       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 };
+       if(readKeyfile("iclass_decryptionkey.bin", 16, key))
+       {
+               usage_hf_iclass_decrypt();
+               return 1;
+       }
+       PrintAndLog("Decryption file found... ");
+       char opt = param_getchar(Cmd, 0);
+       if (strlen(Cmd)<1 || opt == 'h')
+               return usage_hf_iclass_decrypt();
+
+       //Open the tagdump-file
+       FILE *f;
+       char filename[FILE_PATH_SIZE];
+       if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
+       {
+               f = fopen(filename, "rb");
+       }else{
+               return usage_hf_iclass_decrypt();
+       }
+
+       fseek(f, 0, SEEK_END);
+       long fsize = ftell(f);
+       fseek(f, 0, SEEK_SET);
+       uint8_t enc_dump[8] = {0};
+       uint8_t *decrypted = malloc(fsize);
+       des3_context ctx = { DES_DECRYPT ,{ 0 } };
+       des3_set2key_dec( &ctx, key);
+       size_t bytes_read = fread(enc_dump, 1, 8, f);
+
+       //Use the first block (CSN) for filename
+       char outfilename[FILE_PATH_SIZE] = { 0 };
+       snprintf(outfilename,FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
+                        enc_dump[0],enc_dump[1],enc_dump[2],enc_dump[3],
+                        enc_dump[4],enc_dump[5],enc_dump[6],enc_dump[7]);
+
+       size_t blocknum =0;
+       while(bytes_read == 8)
+       {
+               if(blocknum < 7)
+               {
+                       memcpy(decrypted+(blocknum*8), enc_dump, 8);
+               }else{
+                       des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
+               }
+               printvar("decrypted block", decrypted +(blocknum*8), 8);
+               bytes_read = fread(enc_dump, 1, 8, f);
+               blocknum++;
+       }
+       fclose(f);
+
+       saveFile(outfilename,"bin", decrypted, blocknum*8);
+
+       return 0;
+}
 
 int CmdHFiClass_iso14443A_write(const char *Cmd)
 {
@@ -508,7 +617,7 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
        diversifyKey(CSN,KEY, div_key);
 
        PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
-       doMAC(CCNR, 12,div_key, MAC);
+       doMAC(CCNR, div_key, MAC);
 
        UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
        memcpy(c2.d.asBytes, bldata, 8);
@@ -583,9 +692,10 @@ 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"},
        {"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" },
        {NULL, NULL, 0, NULL}
 };
 
Impressum, Datenschutz