Преглед изворни кода

1.5.0 - New update, new scene
Changes:
- Added new scene with information about why nonces aren't collected (skipped/invalid)
- Removed some old code, breaking compability with old firmware
- App renamed from "Flipper (Mifare) Nested" to "Flipper Nested"

Once again, I hope I didn't break everything.

AloneLiberty пре 2 година
родитељ
комит
86fc49fb72

+ 2 - 2
application.fam

@@ -1,6 +1,6 @@
 App(
 App(
     appid="mifare_nested",
     appid="mifare_nested",
-    name="Flipper (Mifare) Nested",
+    name="Flipper Nested",
     apptype=FlipperAppType.EXTERNAL,
     apptype=FlipperAppType.EXTERNAL,
     entry_point="mifare_nested_app",
     entry_point="mifare_nested_app",
     requires=[
     requires=[
@@ -21,5 +21,5 @@ App(
     fap_author="AloneLiberty",
     fap_author="AloneLiberty",
     fap_description="Recover Mifare Classic keys",
     fap_description="Recover Mifare Classic keys",
     fap_weburl="https://github.com/AloneLiberty/FlipperNested",
     fap_weburl="https://github.com/AloneLiberty/FlipperNested",
-    fap_version=(1, 4)
+    fap_version="1.5.0"
 )
 )

+ 0 - 22
lib/nested/nested.c

@@ -5,28 +5,6 @@
 #include "../../lib/crypto1/crypto1.h"
 #include "../../lib/crypto1/crypto1.h"
 #define TAG "Nested"
 #define TAG "Nested"
 
 
-void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest) {
-    furi_assert(dest);
-    furi_assert(len <= 8);
-
-    while(len--) {
-        dest[len] = (uint8_t)src;
-        src >>= 8;
-    }
-}
-
-uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len) {
-    furi_assert(src);
-    furi_assert(len <= 8);
-
-    uint64_t res = 0;
-    while(len--) {
-        res = (res << 8) | (*src);
-        src++;
-    }
-    return res;
-}
-
 uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) {
 uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) {
     uint16_t crc = 0x6363; // NFCA_CRC_INIT
     uint16_t crc = 0x6363; // NFCA_CRC_INIT
     uint8_t byte = 0;
     uint8_t byte = 0;

+ 1 - 0
mifare_nested.c

@@ -396,6 +396,7 @@ void mifare_nested_blink_stop(MifareNested* mifare_nested) {
 
 
 int32_t mifare_nested_app(void* p) {
 int32_t mifare_nested_app(void* p) {
     UNUSED(p);
     UNUSED(p);
+
     MifareNested* mifare_nested = mifare_nested_alloc();
     MifareNested* mifare_nested = mifare_nested_alloc();
 
 
     scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart);
     scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart);

+ 2 - 1
mifare_nested_i.h

@@ -21,7 +21,7 @@
 #include <gui/modules/variable_item_list.h>
 #include <gui/modules/variable_item_list.h>
 #include "mifare_nested_icons.h"
 #include "mifare_nested_icons.h"
 
 
-#define NESTED_VERSION_APP "1.4.6"
+#define NESTED_VERSION_APP "1.5.0"
 #define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
 #define NESTED_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNested"
 #define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
 #define NESTED_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery"
 #define NESTED_NONCE_FORMAT_VERSION "3"
 #define NESTED_NONCE_FORMAT_VERSION "3"
@@ -99,6 +99,7 @@ struct MifareNested {
 
 
     NestedState* nested_state;
     NestedState* nested_state;
     CheckKeysState* keys_state;
     CheckKeysState* keys_state;
+    SaveNoncesResult_t* save_state;
 
 
     MifareNestedWorkerState collecting_type;
     MifareNestedWorkerState collecting_type;
 
 

+ 63 - 20
mifare_nested_worker.c

@@ -296,7 +296,7 @@ uint32_t mifare_nested_worker_predict_delay(
     }
     }
 
 
     // This part of attack is my attempt to implement it on Flipper.
     // This part of attack is my attempt to implement it on Flipper.
-    // Proxmark can do this in 2 fucking steps, but idk how.
+    // Check README.md for more info
 
 
     // First, we find RPNG rounds per 1000 us
     // First, we find RPNG rounds per 1000 us
     for(uint32_t rtr = 0; rtr < 25; rtr++) {
     for(uint32_t rtr = 0; rtr < 25; rtr++) {
@@ -448,7 +448,7 @@ uint32_t mifare_nested_worker_predict_delay(
     return 1;
     return 1;
 }
 }
 
 
-void mifare_nested_worker_write_nonces(
+SaveNoncesResult_t* mifare_nested_worker_write_nonces(
     FuriHalNfcDevData* data,
     FuriHalNfcDevData* data,
     Storage* storage,
     Storage* storage,
     NonceList_t* nonces,
     NonceList_t* nonces,
@@ -459,6 +459,11 @@ void mifare_nested_worker_write_nonces(
     uint32_t distance) {
     uint32_t distance) {
     FuriString* path = furi_string_alloc();
     FuriString* path = furi_string_alloc();
     Stream* file_stream = file_stream_alloc(storage);
     Stream* file_stream = file_stream_alloc(storage);
+    SaveNoncesResult_t* result = malloc(sizeof(SaveNoncesResult_t));
+    result->saved = 0;
+    result->invalid = 0;
+    result->skipped = 0;
+
     mifare_nested_worker_get_nonces_file_path(data, path);
     mifare_nested_worker_get_nonces_file_path(data, path);
 
 
     file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
     file_stream_open(file_stream, furi_string_get_cstr(path), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS);
@@ -472,23 +477,26 @@ void mifare_nested_worker_write_nonces(
     for(uint8_t tries = 0; tries < tries_count; tries++) {
     for(uint8_t tries = 0; tries < tries_count; tries++) {
         for(uint8_t sector = 0; sector < sector_count; sector++) {
         for(uint8_t sector = 0; sector < sector_count; sector++) {
             for(uint8_t key_type = 0; key_type < 2; key_type++) {
             for(uint8_t key_type = 0; key_type < 2; key_type++) {
-                if(nonces->nonces[sector][key_type][tries]->collected &&
-                   !nonces->nonces[sector][key_type][tries]->skipped) {
+                if(nonces->nonces[sector][key_type][tries]->invalid) {
+                    result->invalid++;
+                } else if(nonces->nonces[sector][key_type][tries]->skipped) {
+                    result->skipped++;
+                } else if(nonces->nonces[sector][key_type][tries]->collected) {
                     if(nonces->nonces[sector][key_type][tries]->hardnested) {
                     if(nonces->nonces[sector][key_type][tries]->hardnested) {
-                        FuriString* path = furi_string_alloc();
+                        FuriString* hardnested_path = furi_string_alloc();
                         mifare_nested_worker_get_hardnested_file_path(
                         mifare_nested_worker_get_hardnested_file_path(
-                            data, path, sector, key_type);
+                            data, hardnested_path, sector, key_type);
 
 
                         FuriString* str = furi_string_alloc_printf(
                         FuriString* str = furi_string_alloc_printf(
                             "HardNested: Key %c cuid 0x%08lx file %s sec %u\n",
                             "HardNested: Key %c cuid 0x%08lx file %s sec %u\n",
                             !key_type ? 'A' : 'B',
                             !key_type ? 'A' : 'B',
                             nonces->cuid,
                             nonces->cuid,
-                            furi_string_get_cstr(path),
+                            furi_string_get_cstr(hardnested_path),
                             sector);
                             sector);
 
 
                         stream_write_string(file_stream, str);
                         stream_write_string(file_stream, str);
 
 
-                        furi_string_free(path);
+                        furi_string_free(hardnested_path);
                         furi_string_free(str);
                         furi_string_free(str);
                     } else {
                     } else {
                         FuriString* str = furi_string_alloc_printf(
                         FuriString* str = furi_string_alloc_printf(
@@ -515,6 +523,8 @@ void mifare_nested_worker_write_nonces(
                         stream_write_string(file_stream, str);
                         stream_write_string(file_stream, str);
                         furi_string_free(str);
                         furi_string_free(str);
                     }
                     }
+
+                    result->saved++;
                 }
                 }
             }
             }
         }
         }
@@ -529,10 +539,20 @@ void mifare_nested_worker_write_nonces(
     }
     }
 
 
     free_nonces(nonces, sector_count, free_tries_count);
     free_nonces(nonces, sector_count, free_tries_count);
-    furi_string_free(path);
     file_stream_close(file_stream);
     file_stream_close(file_stream);
     free(file_stream);
     free(file_stream);
+
+    if(!result->saved) {
+        FURI_LOG_E(TAG, "No nonces collected, removing file...");
+        if(!storage_simply_remove(storage, furi_string_get_cstr(path))) {
+            FURI_LOG_E(TAG, "Failed to remove .nonces file");
+        }
+    }
+
+    furi_string_free(path);
     furi_record_close(RECORD_STORAGE);
     furi_record_close(RECORD_STORAGE);
+
+    return result;
 }
 }
 
 
 bool mifare_nested_worker_check_initial_keys(
 bool mifare_nested_worker_check_initial_keys(
@@ -759,7 +779,7 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste
                         mifare_nested_worker_get_block_by_sector(sector),
                         mifare_nested_worker_get_block_by_sector(sector),
                         key_type);
                         key_type);
 
 
-                    info->skipped = true;
+                    info->invalid = true;
 
 
                     nonces.nonces[sector][key_type][0] = info;
                     nonces.nonces[sector][key_type][0] = info;
 
 
@@ -818,12 +838,20 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste
         break;
         break;
     }
     }
 
 
-    mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
+    SaveNoncesResult_t* result =
+        mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
 
 
     free(mf_data);
     free(mf_data);
 
 
-    mifare_nested_worker->callback(
-        MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    if(result->saved) {
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    } else {
+        mifare_nested_worker->context->save_state = result;
+
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
+    }
 
 
     nfc_deactivate();
     nfc_deactivate();
 }
 }
@@ -930,7 +958,7 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_
                     mifare_nested_worker_get_block_by_sector(sector),
                     mifare_nested_worker_get_block_by_sector(sector),
                     key_type);
                     key_type);
 
 
-                info->skipped = true;
+                info->invalid = true;
 
 
                 nonces.nonces[sector][key_type][0] = info;
                 nonces.nonces[sector][key_type][0] = info;
                 mifare_nested_worker->context->nonces = &nonces;
                 mifare_nested_worker->context->nonces = &nonces;
@@ -1059,12 +1087,20 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_
         }
         }
     }
     }
 
 
-    mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
+    SaveNoncesResult_t* result =
+        mifare_nested_worker_write_nonces(&data, storage, &nonces, 1, 1, sector_count, 0, 0);
 
 
     free(mf_data);
     free(mf_data);
 
 
-    mifare_nested_worker->callback(
-        MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    if(result->saved) {
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    } else {
+        mifare_nested_worker->context->save_state = result;
+
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
+    }
 
 
     nfc_deactivate();
     nfc_deactivate();
 }
 }
@@ -1368,13 +1404,20 @@ void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worke
         break;
         break;
     }
     }
 
 
-    mifare_nested_worker_write_nonces(
+    SaveNoncesResult_t* result = mifare_nested_worker_write_nonces(
         &data, storage, &nonces, tries_count, 3, sector_count, delay, distance);
         &data, storage, &nonces, tries_count, 3, sector_count, delay, distance);
 
 
     free(mf_data);
     free(mf_data);
 
 
-    mifare_nested_worker->callback(
-        MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    if(result->saved) {
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoncesCollected, mifare_nested_worker->context);
+    } else {
+        mifare_nested_worker->context->save_state = result;
+
+        mifare_nested_worker->callback(
+            MifareNestedWorkerEventNoNoncesCollected, mifare_nested_worker->context);
+    }
 
 
     nfc_deactivate();
     nfc_deactivate();
 }
 }

+ 9 - 1
mifare_nested_worker.h

@@ -22,6 +22,7 @@ typedef enum {
     MifareNestedWorkerEventReserved = 1000,
     MifareNestedWorkerEventReserved = 1000,
 
 
     MifareNestedWorkerEventNoTagDetected,
     MifareNestedWorkerEventNoTagDetected,
+    MifareNestedWorkerEventNoNoncesCollected,
     MifareNestedWorkerEventNoncesCollected,
     MifareNestedWorkerEventNoncesCollected,
     MifareNestedWorkerEventCollecting,
     MifareNestedWorkerEventCollecting,
 
 
@@ -64,8 +65,9 @@ typedef struct {
     uint32_t target_nt[2];
     uint32_t target_nt[2];
     uint32_t target_ks[2];
     uint32_t target_ks[2];
     uint8_t parity[2][4];
     uint8_t parity[2][4];
-    bool collected;
     bool skipped;
     bool skipped;
+    bool invalid;
+    bool collected;
     bool hardnested;
     bool hardnested;
 } Nonces;
 } Nonces;
 
 
@@ -87,3 +89,9 @@ typedef struct {
     uint32_t sector_keys;
     uint32_t sector_keys;
     bool tag_lost;
     bool tag_lost;
 } KeyInfo_t;
 } KeyInfo_t;
+
+typedef struct {
+    uint32_t saved;
+    uint32_t invalid;
+    uint32_t skipped;
+} SaveNoncesResult_t;

+ 1 - 1
scenes/mifare_nested_scene_about.c

@@ -51,7 +51,7 @@ void mifare_nested_scene_about_on_enter(void* context) {
         14,
         14,
         AlignCenter,
         AlignCenter,
         AlignBottom,
         AlignBottom,
-        "\e#\e! Flipper (Mifare) Nested \e!\n",
+        "\e#\e! Flipper Nested \e!\n",
         false);
         false);
     widget_add_text_scroll_element(
     widget_add_text_scroll_element(
         mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
         mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));

+ 1 - 8
scenes/mifare_nested_scene_check.c

@@ -56,14 +56,7 @@ bool mifare_nested_scene_check_on_event(void* context, SceneManagerEvent event)
     bool consumed = false;
     bool consumed = false;
 
 
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
-        if(event.event == MifareNestedWorkerEventNoncesCollected) {
-            scene_manager_next_scene(
-                mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
-            consumed = true;
-        } else if(event.event == MifareNestedWorkerEventAttackFailed) {
-            scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
-            consumed = true;
-        } else if(event.event == MifareNestedWorkerEventCollecting) {
+        if(event.event == MifareNestedWorkerEventCollecting) {
             if(mifare_nested->run == NestedRunAttack) {
             if(mifare_nested->run == NestedRunAttack) {
                 if(mifare_nested->settings->only_hardnested) {
                 if(mifare_nested->settings->only_hardnested) {
                     FURI_LOG_I("MifareNested", "Using Hard Nested because user settings");
                     FURI_LOG_I("MifareNested", "Using Hard Nested because user settings");

+ 0 - 7
scenes/mifare_nested_scene_check_keys.c

@@ -84,13 +84,6 @@ bool mifare_nested_scene_check_keys_on_event(void* context, SceneManagerEvent ev
         if(event.event == GuiButtonTypeCenter) {
         if(event.event == GuiButtonTypeCenter) {
             scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
             scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
             consumed = true;
             consumed = true;
-        } else if(event.event == MifareNestedWorkerEventNoncesCollected) {
-            scene_manager_next_scene(
-                mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
-            consumed = true;
-        } else if(event.event == MifareNestedWorkerEventNeedKey) {
-            scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneNoKeys);
-            consumed = true;
         } else if(event.event == MifareNestedWorkerEventKeysFound) {
         } else if(event.event == MifareNestedWorkerEventKeysFound) {
             scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys);
             scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys);
             consumed = true;
             consumed = true;

+ 4 - 0
scenes/mifare_nested_scene_collecting.c

@@ -120,6 +120,10 @@ bool mifare_nested_scene_collecting_on_event(void* context, SceneManagerEvent ev
             scene_manager_next_scene(
             scene_manager_next_scene(
                 mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
                 mifare_nested->scene_manager, MifareNestedSceneNoncesCollected);
             consumed = true;
             consumed = true;
+        } else if(event.event == MifareNestedWorkerEventNoNoncesCollected) {
+            scene_manager_next_scene(
+                mifare_nested->scene_manager, MifareNestedSceneNoNoncesCollected);
+            consumed = true;
         } else if(event.event == MifareNestedWorkerEventAttackFailed) {
         } else if(event.event == MifareNestedWorkerEventAttackFailed) {
             scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
             scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed);
             consumed = true;
             consumed = true;

+ 2 - 1
scenes/mifare_nested_scene_config.h

@@ -10,4 +10,5 @@ ADD_SCENE(mifare_nested, about, About)
 ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce)
 ADD_SCENE(mifare_nested, static_encrypted_nonce, StaticEncryptedNonce)
 ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery)
 ADD_SCENE(mifare_nested, need_key_recovery, NeedKeyRecovery)
 ADD_SCENE(mifare_nested, need_collection, NeedCollection)
 ADD_SCENE(mifare_nested, need_collection, NeedCollection)
-ADD_SCENE(mifare_nested, settings, Settings)
+ADD_SCENE(mifare_nested, settings, Settings)
+ADD_SCENE(mifare_nested, no_nonces_collected, NoNoncesCollected)

+ 94 - 0
scenes/mifare_nested_scene_no_nonces_collected.c

@@ -0,0 +1,94 @@
+#include "../mifare_nested_i.h"
+
+void mifare_nested_scene_no_nonces_collected_widget_callback(
+    GuiButtonType result,
+    InputType type,
+    void* context) {
+    MifareNested* mifare_nested = context;
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(mifare_nested->view_dispatcher, result);
+    }
+}
+
+void mifare_nested_scene_no_nonces_collected_on_enter(void* context) {
+    MifareNested* mifare_nested = context;
+    Widget* widget = mifare_nested->widget;
+    SaveNoncesResult_t* save_state = mifare_nested->save_state;
+
+    notification_message(mifare_nested->notifications, &sequence_error);
+
+    widget_add_icon_element(widget, 73, 12, &I_DolphinCry);
+    widget_add_string_element(
+        widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "No nonces collected");
+
+    uint32_t index = 12;
+
+    if(save_state->skipped) {
+        char append_skipped[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'};
+        if(save_state->skipped != 1) {
+            append_skipped[6] = 's';
+        }
+
+        char draw_str[32] = {};
+        snprintf(
+            draw_str, sizeof(draw_str), "Skipped: %lu %s", save_state->skipped, append_skipped);
+
+        widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str);
+
+        widget_add_string_element(
+            widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(already has keys)");
+
+        index += 20;
+    }
+
+    if(save_state->invalid) {
+        char append_invalid[8] = {'s', 'e', 'c', 't', 'o', 'r', ' ', '\0'};
+        if(save_state->invalid != 1) {
+            append_invalid[6] = 's';
+        }
+
+        char draw_str[32] = {};
+        snprintf(
+            draw_str, sizeof(draw_str), "Invalid: %lu %s", save_state->invalid, append_invalid);
+
+        widget_add_string_element(widget, 0, index, AlignLeft, AlignTop, FontSecondary, draw_str);
+
+        widget_add_string_element(
+            widget, 0, index + 10, AlignLeft, AlignTop, FontSecondary, "(can't auth)");
+    }
+
+    free(save_state);
+
+    widget_add_button_element(
+        widget,
+        GuiButtonTypeLeft,
+        "Back",
+        mifare_nested_scene_no_nonces_collected_widget_callback,
+        mifare_nested);
+
+    // Setup and start worker
+    view_dispatcher_switch_to_view(mifare_nested->view_dispatcher, MifareNestedViewWidget);
+}
+
+bool mifare_nested_scene_no_nonces_collected_on_event(void* context, SceneManagerEvent event) {
+    MifareNested* mifare_nested = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == GuiButtonTypeCenter || event.event == GuiButtonTypeLeft) {
+            scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
+            consumed = true;
+        }
+    } else if(event.type == SceneManagerEventTypeBack) {
+        scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0);
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void mifare_nested_scene_no_nonces_collected_on_exit(void* context) {
+    MifareNested* mifare_nested = context;
+
+    widget_reset(mifare_nested->widget);
+}