From 4609d7ed93ae218cc1ba9533d19ca56e1f1977da Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 30 May 2023 17:14:27 +0300 Subject: [PATCH] Update FlipperNested https://github.com/AloneLiberty/FlipperNested --- .../external/mifare_nested/application.fam | 2 +- .../mifare_nested/lib/nested/nested.c | 22 ----- .../external/mifare_nested/mifare_nested.c | 1 + .../external/mifare_nested/mifare_nested_i.h | 3 +- .../mifare_nested/mifare_nested_worker.c | 83 ++++++++++++---- .../mifare_nested/mifare_nested_worker.h | 10 +- .../scenes/mifare_nested_scene_about.c | 2 +- .../scenes/mifare_nested_scene_check.c | 9 +- .../scenes/mifare_nested_scene_check_keys.c | 7 -- .../scenes/mifare_nested_scene_collecting.c | 4 + .../scenes/mifare_nested_scene_config.h | 3 +- .../mifare_nested_scene_no_nonces_collected.c | 94 +++++++++++++++++++ 12 files changed, 178 insertions(+), 62 deletions(-) create mode 100644 applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c diff --git a/applications/external/mifare_nested/application.fam b/applications/external/mifare_nested/application.fam index 236abf6d1..5b2c0b466 100644 --- a/applications/external/mifare_nested/application.fam +++ b/applications/external/mifare_nested/application.fam @@ -21,5 +21,5 @@ App( fap_author="AloneLiberty", fap_description="Recover Mifare Classic keys", fap_weburl="https://github.com/AloneLiberty/FlipperNested", - fap_version=(1, 4) + fap_version="1.5.0" ) diff --git a/applications/external/mifare_nested/lib/nested/nested.c b/applications/external/mifare_nested/lib/nested/nested.c index 4d04b99d5..b289b74fb 100644 --- a/applications/external/mifare_nested/lib/nested/nested.c +++ b/applications/external/mifare_nested/lib/nested/nested.c @@ -5,28 +5,6 @@ #include "../../lib/crypto1/crypto1.h" #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 crc = 0x6363; // NFCA_CRC_INIT uint8_t byte = 0; diff --git a/applications/external/mifare_nested/mifare_nested.c b/applications/external/mifare_nested/mifare_nested.c index 237eaef9a..bb6947a91 100644 --- a/applications/external/mifare_nested/mifare_nested.c +++ b/applications/external/mifare_nested/mifare_nested.c @@ -396,6 +396,7 @@ void mifare_nested_blink_stop(MifareNested* mifare_nested) { int32_t mifare_nested_app(void* p) { UNUSED(p); + MifareNested* mifare_nested = mifare_nested_alloc(); scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneStart); diff --git a/applications/external/mifare_nested/mifare_nested_i.h b/applications/external/mifare_nested/mifare_nested_i.h index 59aab5825..69907dcd0 100644 --- a/applications/external/mifare_nested/mifare_nested_i.h +++ b/applications/external/mifare_nested/mifare_nested_i.h @@ -21,7 +21,7 @@ #include #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_RECOVER_KEYS_GITHUB_LINK "https://github.com/AloneLiberty/FlipperNestedRecovery" #define NESTED_NONCE_FORMAT_VERSION "3" @@ -99,6 +99,7 @@ struct MifareNested { NestedState* nested_state; CheckKeysState* keys_state; + SaveNoncesResult_t* save_state; MifareNestedWorkerState collecting_type; diff --git a/applications/external/mifare_nested/mifare_nested_worker.c b/applications/external/mifare_nested/mifare_nested_worker.c index 56d2f2427..7598d28c9 100644 --- a/applications/external/mifare_nested/mifare_nested_worker.c +++ b/applications/external/mifare_nested/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. - // 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 for(uint32_t rtr = 0; rtr < 25; rtr++) { @@ -448,7 +448,7 @@ uint32_t mifare_nested_worker_predict_delay( return 1; } -void mifare_nested_worker_write_nonces( +SaveNoncesResult_t* mifare_nested_worker_write_nonces( FuriHalNfcDevData* data, Storage* storage, NonceList_t* nonces, @@ -459,6 +459,11 @@ void mifare_nested_worker_write_nonces( uint32_t distance) { FuriString* path = furi_string_alloc(); 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); 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 sector = 0; sector < sector_count; sector++) { 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) { - FuriString* path = furi_string_alloc(); + FuriString* hardnested_path = furi_string_alloc(); mifare_nested_worker_get_hardnested_file_path( - data, path, sector, key_type); + data, hardnested_path, sector, key_type); FuriString* str = furi_string_alloc_printf( "HardNested: Key %c cuid 0x%08lx file %s sec %u\n", !key_type ? 'A' : 'B', nonces->cuid, - furi_string_get_cstr(path), + furi_string_get_cstr(hardnested_path), sector); stream_write_string(file_stream, str); - furi_string_free(path); + furi_string_free(hardnested_path); furi_string_free(str); } else { FuriString* str = furi_string_alloc_printf( @@ -515,6 +523,8 @@ void mifare_nested_worker_write_nonces( stream_write_string(file_stream, 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); - furi_string_free(path); file_stream_close(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); + + return result; } 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), key_type); - info->skipped = true; + info->invalid = true; nonces.nonces[sector][key_type][0] = info; @@ -818,12 +838,20 @@ void mifare_nested_worker_collect_nonces_static(MifareNestedWorker* mifare_neste 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); - 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(); } @@ -930,7 +958,7 @@ void mifare_nested_worker_collect_nonces_hard(MifareNestedWorker* mifare_nested_ mifare_nested_worker_get_block_by_sector(sector), key_type); - info->skipped = true; + info->invalid = true; nonces.nonces[sector][key_type][0] = info; 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); - 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(); } @@ -1368,13 +1404,20 @@ void mifare_nested_worker_collect_nonces(MifareNestedWorker* mifare_nested_worke break; } - mifare_nested_worker_write_nonces( + SaveNoncesResult_t* result = mifare_nested_worker_write_nonces( &data, storage, &nonces, tries_count, 3, sector_count, delay, distance); 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(); } diff --git a/applications/external/mifare_nested/mifare_nested_worker.h b/applications/external/mifare_nested/mifare_nested_worker.h index 561620676..2421b35eb 100644 --- a/applications/external/mifare_nested/mifare_nested_worker.h +++ b/applications/external/mifare_nested/mifare_nested_worker.h @@ -22,6 +22,7 @@ typedef enum { MifareNestedWorkerEventReserved = 1000, MifareNestedWorkerEventNoTagDetected, + MifareNestedWorkerEventNoNoncesCollected, MifareNestedWorkerEventNoncesCollected, MifareNestedWorkerEventCollecting, @@ -64,8 +65,9 @@ typedef struct { uint32_t target_nt[2]; uint32_t target_ks[2]; uint8_t parity[2][4]; - bool collected; bool skipped; + bool invalid; + bool collected; bool hardnested; } Nonces; @@ -87,3 +89,9 @@ typedef struct { uint32_t sector_keys; bool tag_lost; } KeyInfo_t; + +typedef struct { + uint32_t saved; + uint32_t invalid; + uint32_t skipped; +} SaveNoncesResult_t; \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c index cb07f81a3..9aa46f698 100644 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c +++ b/applications/external/mifare_nested/scenes/mifare_nested_scene_about.c @@ -51,7 +51,7 @@ void mifare_nested_scene_about_on_enter(void* context) { 14, AlignCenter, AlignBottom, - "\e#\e! Flipper (Mifare) Nested \e!\n", + "\e#\e! Flipper Nested \e!\n", false); widget_add_text_scroll_element( mifare_nested->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c index 4eb344703..45837ff92 100644 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c +++ b/applications/external/mifare_nested/scenes/mifare_nested_scene_check.c @@ -56,14 +56,7 @@ bool mifare_nested_scene_check_on_event(void* context, SceneManagerEvent event) bool consumed = false; 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->settings->only_hardnested) { FURI_LOG_I("MifareNested", "Using Hard Nested because user settings"); diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c index f0071b7aa..b06953eeb 100644 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_check_keys.c +++ b/applications/external/mifare_nested/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) { scene_manager_search_and_switch_to_previous_scene(mifare_nested->scene_manager, 0); 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) { scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneAddedKeys); consumed = true; diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c index 05c96d97d..281210107 100644 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_collecting.c +++ b/applications/external/mifare_nested/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( mifare_nested->scene_manager, MifareNestedSceneNoncesCollected); consumed = true; + } else if(event.event == MifareNestedWorkerEventNoNoncesCollected) { + scene_manager_next_scene( + mifare_nested->scene_manager, MifareNestedSceneNoNoncesCollected); + consumed = true; } else if(event.event == MifareNestedWorkerEventAttackFailed) { scene_manager_next_scene(mifare_nested->scene_manager, MifareNestedSceneFailed); consumed = true; diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h b/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h index 14cf52c4e..648f0bd73 100644 --- a/applications/external/mifare_nested/scenes/mifare_nested_scene_config.h +++ b/applications/external/mifare_nested/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, need_key_recovery, NeedKeyRecovery) ADD_SCENE(mifare_nested, need_collection, NeedCollection) -ADD_SCENE(mifare_nested, settings, Settings) \ No newline at end of file +ADD_SCENE(mifare_nested, settings, Settings) +ADD_SCENE(mifare_nested, no_nonces_collected, NoNoncesCollected) \ No newline at end of file diff --git a/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c b/applications/external/mifare_nested/scenes/mifare_nested_scene_no_nonces_collected.c new file mode 100644 index 000000000..74e2459e8 --- /dev/null +++ b/applications/external/mifare_nested/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); +}