Просмотр исходного кода

Picopass standard KDF dictionary (#2478)

* Split iclass dictionaries based on KDF
* Allow cancelling during key test

Co-authored-by: あく <alleteam@gmail.com>
Eric Betts 2 лет назад
Родитель
Сommit
e22668e196

+ 14 - 1
applications/external/picopass/helpers/iclass_elite_dict.c

@@ -5,6 +5,7 @@
 
 #define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt")
 #define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt")
+#define ICLASS_STANDARD_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_standard_dict.txt")
 
 #define TAG "IclassEliteDict"
 
@@ -25,6 +26,9 @@ bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) {
             (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK);
     } else if(dict_type == IclassEliteDictTypeUser) {
         dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK);
+    } else if(dict_type == IclassStandardDictTypeFlipper) {
+        dict_present =
+            (storage_common_stat(storage, ICLASS_STANDARD_DICT_FLIPPER_NAME, NULL) == FSE_OK);
     }
 
     furi_record_close(RECORD_STORAGE);
@@ -52,6 +56,15 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) {
                 buffered_file_stream_close(dict->stream);
                 break;
             }
+        } else if(dict_type == IclassStandardDictTypeFlipper) {
+            if(!buffered_file_stream_open(
+                   dict->stream,
+                   ICLASS_STANDARD_DICT_FLIPPER_NAME,
+                   FSAM_READ,
+                   FSOM_OPEN_EXISTING)) {
+                buffered_file_stream_close(dict->stream);
+                break;
+            }
         }
 
         // Read total amount of keys
@@ -148,4 +161,4 @@ bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key) {
 
     furi_string_free(key_str);
     return key_added;
-}
+}

+ 2 - 1
applications/external/picopass/helpers/iclass_elite_dict.h

@@ -9,6 +9,7 @@
 typedef enum {
     IclassEliteDictTypeUser,
     IclassEliteDictTypeFlipper,
+    IclassStandardDictTypeFlipper,
 } IclassEliteDictType;
 
 typedef struct IclassEliteDict IclassEliteDict;
@@ -25,4 +26,4 @@ bool iclass_elite_dict_get_next_key(IclassEliteDict* dict, uint8_t* key);
 
 bool iclass_elite_dict_rewind(IclassEliteDict* dict);
 
-bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key);
+bool iclass_elite_dict_add_key(IclassEliteDict* dict, uint8_t* key);

+ 19 - 27
applications/external/picopass/picopass_worker.c

@@ -172,14 +172,18 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) {
     return ERR_NONE;
 }
 
-static ReturnCode picopass_auth_dict(
-    uint8_t* csn,
-    PicopassPacs* pacs,
-    uint8_t* div_key,
-    IclassEliteDictType dict_type,
-    bool elite) {
+static ReturnCode
+    picopass_auth_dict(PicopassWorker* picopass_worker, IclassEliteDictType dict_type) {
     rfalPicoPassReadCheckRes rcRes;
     rfalPicoPassCheckRes chkRes;
+    bool elite = (dict_type != IclassStandardDictTypeFlipper);
+
+    PicopassDeviceData* dev_data = picopass_worker->dev_data;
+    PicopassBlock* AA1 = dev_data->AA1;
+    PicopassPacs* pacs = &dev_data->pacs;
+
+    uint8_t* csn = AA1[PICOPASS_CSN_BLOCK_INDEX].data;
+    uint8_t* div_key = AA1[PICOPASS_KD_BLOCK_INDEX].data;
 
     ReturnCode err = ERR_PARAM;
 
@@ -204,7 +208,8 @@ static ReturnCode picopass_auth_dict(
     while(iclass_elite_dict_get_next_key(dict, key)) {
         FURI_LOG_D(
             TAG,
-            "Try to auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x",
+            "Try to %s auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x",
+            elite ? "elite" : "standard",
             index++,
             key[0],
             key[1],
@@ -230,6 +235,8 @@ static ReturnCode picopass_auth_dict(
             memcpy(pacs->key, key, PICOPASS_BLOCK_LEN);
             break;
         }
+
+        if(picopass_worker->state != PicopassWorkerStateDetect) break;
     }
 
     iclass_elite_dict_free(dict);
@@ -237,38 +244,23 @@ static ReturnCode picopass_auth_dict(
     return err;
 }
 
-ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) {
+ReturnCode picopass_auth(PicopassWorker* picopass_worker) {
     ReturnCode err;
 
     FURI_LOG_I(TAG, "Starting system dictionary attack [Standard KDF]");
-    err = picopass_auth_dict(
-        AA1[PICOPASS_CSN_BLOCK_INDEX].data,
-        pacs,
-        AA1[PICOPASS_KD_BLOCK_INDEX].data,
-        IclassEliteDictTypeFlipper,
-        false);
+    err = picopass_auth_dict(picopass_worker, IclassStandardDictTypeFlipper);
     if(err == ERR_NONE) {
         return ERR_NONE;
     }
 
     FURI_LOG_I(TAG, "Starting user dictionary attack [Elite KDF]");
-    err = picopass_auth_dict(
-        AA1[PICOPASS_CSN_BLOCK_INDEX].data,
-        pacs,
-        AA1[PICOPASS_KD_BLOCK_INDEX].data,
-        IclassEliteDictTypeUser,
-        true);
+    err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeUser);
     if(err == ERR_NONE) {
         return ERR_NONE;
     }
 
     FURI_LOG_I(TAG, "Starting system dictionary attack [Elite KDF]");
-    err = picopass_auth_dict(
-        AA1[PICOPASS_CSN_BLOCK_INDEX].data,
-        pacs,
-        AA1[PICOPASS_KD_BLOCK_INDEX].data,
-        IclassEliteDictTypeFlipper,
-        true);
+    err = picopass_auth_dict(picopass_worker, IclassEliteDictTypeFlipper);
     if(err == ERR_NONE) {
         return ERR_NONE;
     }
@@ -520,7 +512,7 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) {
             }
 
             if(nextState == PicopassWorkerEventSuccess) {
-                err = picopass_auth(AA1, pacs);
+                err = picopass_auth(picopass_worker);
                 if(err != ERR_NONE) {
                     FURI_LOG_E(TAG, "picopass_try_auth error %d", err);
                     nextState = PicopassWorkerEventFail;

+ 0 - 12
assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt

@@ -1,16 +1,10 @@
 
 ## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic
 
-# AA1
-AEA684A6DAB23278
 # key1/Kc from PicoPass 2k documentation
 7665544332211000
 # SAGEM
 0123456789ABCDEF
-# from loclass demo file.
-5b7c62c491c11b39
-# Kd from PicoPass 2k documentation
-F0E1D2C3B4A59687
 # PicoPass Default Exchange Key
 5CBCF1DA45D5FB4F
 # From HID multiclassSE reader
@@ -19,12 +13,6 @@ F0E1D2C3B4A59687
 6EFD46EFCBB3C875
 E033CA419AEE43F9
 
-# iCopy-x DRM keys
-# iCL tags
-2020666666668888
-# iCS tags reversed from the SOs
-6666202066668888
-
 # default picopass KD / Page 0 / Book 1
 FDCB5A52EA8F3090
 237FF9079863DF44

+ 47 - 0
assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt

@@ -0,0 +1,47 @@
+
+## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic
+
+# AA1
+AEA684A6DAB23278
+# key1/Kc from PicoPass 2k documentation
+7665544332211000
+# SAGEM
+0123456789ABCDEF
+# from loclass demo file.
+5b7c62c491c11b39
+# Kd from PicoPass 2k documentation
+F0E1D2C3B4A59687
+# PicoPass Default Exchange Key
+5CBCF1DA45D5FB4F
+# From HID multiclassSE reader
+31ad7ebd2f282168
+# From pastebin: https://pastebin.com/uHqpjiuU
+6EFD46EFCBB3C875
+E033CA419AEE43F9
+
+# iCopy-x DRM keys
+# iCL tags
+2020666666668888
+# iCS tags reversed from the SOs
+6666202066668888
+
+# default picopass KD / Page 0 / Book 1
+FDCB5A52EA8F3090
+237FF9079863DF44
+5ADC25FB27181D32
+83B881F2936B2E49
+43644E61EE866BA5
+897034143D016080
+82D17B44C0122963
+4895CA7DE65E2025
+DADAD4C57BE271B7
+E41E9EDEF5719ABF
+293D275EC3AF9C7F
+C3C169251B8A70FB
+F41DAF58B20C8B91
+28877A609EC0DD2B
+66584C91EE80D5E5
+C1B74D7478053AE2
+
+# default iCLASS RFIDeas
+6B65797374726B72