diff --git a/LICENSE b/LICENSE index 8fb0d138897..0a456052c07 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 DerSkythe +Copyright (c) 2024 DerSkythe Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ad8453fff0e..c2ece90982a 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ We do not condone illegal activity and strongly encourage keeping transmissions ## Installation -The application is included in the standard firmware package of [Unleashed Firmware](https://github.com/DarkFlippers/unleashed-firmware). +The application is included in the standard firmware package of [Unleashed Firmware](https://github.com/DarkFlippers/unleashed-firmware). You just need to install the [latest firmware](https://github.com/DarkFlippers/unleashed-firmware/releases/latest).
You can also download the [release](https://github.com/derskythe/flipperzero-subbrute/releases/latest) and unzip/untar it to the `SD Card/apps/Sub-GHz` directory.
> [!WARNING] -> +> > The application is not compatible with the official firmware version. > Also, it has not been tested on other firmware versions other than [Unleashed Firmware](https://github.com/DarkFlippers/unleashed-firmware) and [OFW](https://github.com/flipperdevices/flipperzero-firmware). @@ -30,11 +30,11 @@ You can also download the [release](https://github.com/derskythe/flipperzero-sub ![image](https://github.com/DarkFlippers/flipperzero-subbrute/assets/31771569/9f428d6e-59fd-4517-895d-fb185f8d884f) -Here you can select the protocol and frequency that will be used for bruteforce. +Here you can select the protocol and frequency that will be used for bruteforce. According to our observations, `CAME 12bit 433MHz` is the most common protocol, so it is selected by default. To identify other devices and protocols, you should inspect the device. -According to the protocol, when probe a key, each value is sent 3 times. -Most of the devices this works but there are devices that don't work and more repetitions are needed. +According to the protocol, when probe a key, each value is sent 3 times. +Most of the devices this works but there are devices that don't work and more repetitions are needed. The number of repetitions can be increased with the right button, the left button decreases the value. The negative side of increasing the number of repetitions will be a longer key find time. @@ -88,6 +88,7 @@ The negative side of increasing the number of repetitions will be a longer key f - Chamberlain 9bit 300MHz - Chamberlain 9bit 315MHz +- Chamberlain 9bit 318MHz - Chamberlain 9bit 390MHz - Chamberlain 9bit 433MHz - Chamberlain 8bit 300MHz @@ -106,7 +107,7 @@ The negative side of increasing the number of repetitions will be a longer key f ### UNILARM > [!NOTE] -> +> > Only dip switch combinations, not full 25bit bruteforce - UNILARM 25bit 330MHz (TE: 209μs) @@ -115,7 +116,7 @@ The negative side of increasing the number of repetitions will be a longer key f ### SMC5326 > [!NOTE] -> +> > Only dip switch combinations, not full 25bit bruteforce - SMC5326 25bit 330MHz (TE: 320μs) @@ -124,7 +125,7 @@ The negative side of increasing the number of repetitions will be a longer key f ### PT2260 > [!NOTE] -> +> > Only for 8 dip switch remote, not full 24bit bruteforce - PT2260 24bit 315MHz (TE: 286μs) diff --git a/helpers/subbrute_radio_device_loader.c b/helpers/subbrute_radio_device_loader.c index 6fcfde8726f..9a7a1fe24d5 100644 --- a/helpers/subbrute_radio_device_loader.c +++ b/helpers/subbrute_radio_device_loader.c @@ -46,6 +46,7 @@ bool subbrute_radio_device_loader_is_connect_external(const char* name) { if(!is_otg_enabled) { subbrute_radio_device_loader_power_off(); } + return is_connect; } diff --git a/helpers/subbrute_worker.c b/helpers/subbrute_worker.c index 2061f7c8187..45a67a75aaf 100644 --- a/helpers/subbrute_worker.c +++ b/helpers/subbrute_worker.c @@ -72,6 +72,7 @@ bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step) { furi_assert(instance); if(!subbrute_worker_can_manual_transmit(instance)) { FURI_LOG_W(TAG, "Cannot set step during running mode"); + return false; } @@ -205,6 +206,7 @@ void subbrute_worker_stop(SubBruteWorker* instance) { furi_assert(instance); if(!instance->worker_running) { + return; } @@ -264,21 +266,14 @@ bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t ste stream, instance->file, step, instance->bits, instance->te, instance->repeat); } - // size_t written = stream_write_string(stream, payload); - // if(written <= 0) { - // FURI_LOG_W(TAG, "Error creating packet! EXIT"); - // result = false; - // } else { subbrute_worker_subghz_transmit(instance, flipper_format); result = true; #if FURI_DEBUG FURI_LOG_D(TAG, "Manual transmit done"); #endif - // } flipper_format_free(flipper_format); - // furi_string_free(payload); return result; } @@ -366,11 +361,13 @@ int32_t subbrute_worker_thread(void* context) { if(!instance->worker_running) { FURI_LOG_W(TAG, "Worker is not set to running state!"); + return -1; } if(instance->state != SubBruteWorkerStateReady && instance->state != SubBruteWorkerStateFinished) { FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state); + return -2; } #ifdef FURI_DEBUG @@ -411,15 +408,6 @@ int32_t subbrute_worker_thread(void* context) { //furi_delay_ms(SUBBRUTE_MANUAL_TRANSMIT_INTERVAL / 4); #endif - // size_t written = stream_write_stream_write_string(stream, payload); - // if(written <= 0) { - // FURI_LOG_W(TAG, "Error creating packet! BREAK"); - // instance->worker_running = false; - // local_state = SubBruteWorkerStateIDLE; - // furi_string_free(payload); - // break; - // } - subbrute_worker_subghz_transmit(instance, flipper_format); if(instance->step + 1 > instance->max_value) { @@ -427,12 +415,11 @@ int32_t subbrute_worker_thread(void* context) { FURI_LOG_I(TAG, "Worker finished to end"); #endif local_state = SubBruteWorkerStateFinished; - // furi_string_free(payload); + break; } instance->step++; - // furi_string_free(payload); furi_delay_ms(instance->tx_timeout_ms); } @@ -446,6 +433,7 @@ int32_t subbrute_worker_thread(void* context) { #ifdef FURI_DEBUG FURI_LOG_I(TAG, "Worker stop"); #endif + return 0; } @@ -473,18 +461,6 @@ void subbrute_worker_set_te(SubBruteWorker* instance, uint32_t te) { instance->te = te; } -// void subbrute_worker_timeout_inc(SubBruteWorker* instance) { -// if(instance->tx_timeout_ms < 255) { -// instance->tx_timeout_ms++; -// } -// } - -// void subbrute_worker_timeout_dec(SubBruteWorker* instance) { -// if(instance->tx_timeout_ms > 0) { -// instance->tx_timeout_ms--; -// } -// } - bool subbrute_worker_is_tx_allowed(SubBruteWorker* instance, uint32_t value) { furi_assert(instance); bool res = false; diff --git a/scenes/subbrute_scene_load_file.c b/scenes/subbrute_scene_load_file.c index 391001a54a9..aa787694071 100644 --- a/scenes/subbrute_scene_load_file.c +++ b/scenes/subbrute_scene_load_file.c @@ -91,5 +91,6 @@ void subbrute_scene_load_file_on_exit(void* context) { bool subbrute_scene_load_file_on_event(void* context, SceneManagerEvent event) { UNUSED(context); UNUSED(event); + return false; } diff --git a/scenes/subbrute_scene_save_name.c b/scenes/subbrute_scene_save_name.c index 7628a477a8c..4a82ff95319 100644 --- a/scenes/subbrute_scene_save_name.c +++ b/scenes/subbrute_scene_save_name.c @@ -76,6 +76,7 @@ bool subbrute_scene_save_name_on_event(void* context, SceneManagerEvent event) { instance->scene_manager, SubBruteSceneSetupAttack); } } + return consumed; } diff --git a/scenes/subbrute_scene_save_success.c b/scenes/subbrute_scene_save_success.c index 20b1a0de416..fbfddb3bd6d 100644 --- a/scenes/subbrute_scene_save_success.c +++ b/scenes/subbrute_scene_save_success.c @@ -31,6 +31,7 @@ bool subbrute_scene_save_success_on_event(void* context, SceneManagerEvent event return true; } } + return false; } diff --git a/scenes/subbrute_scene_setup_extra.c b/scenes/subbrute_scene_setup_extra.c index 5e8e05bc9ba..ef26b5d99de 100644 --- a/scenes/subbrute_scene_setup_extra.c +++ b/scenes/subbrute_scene_setup_extra.c @@ -22,7 +22,7 @@ static void setup_extra_td_callback(VariableItem* item) { furi_assert(item); SubBruteState* instance = variable_item_get_context(item); furi_assert(instance); - char buf[6]; + char buf[6] = {0}; const uint8_t index = variable_item_get_current_value_index(item); uint8_t val = subbrute_worker_get_timeout(instance->worker); @@ -76,7 +76,7 @@ static void setup_extra_rep_callback(VariableItem* item) { furi_assert(item); SubBruteState* instance = variable_item_get_context(item); furi_assert(instance); - char buf[6]; + char buf[6] = {0}; const uint8_t index = variable_item_get_current_value_index(item); uint8_t val = subbrute_worker_get_repeats(instance->worker); @@ -130,7 +130,7 @@ static void setup_extra_te_callback(VariableItem* item) { furi_assert(item); SubBruteState* instance = variable_item_get_context(item); furi_assert(instance); - char buf[6]; + char buf[6] = {0}; const uint8_t index = variable_item_get_current_value_index(item); uint32_t val = subbrute_worker_get_te(instance->worker); @@ -182,7 +182,7 @@ static void setup_extra_te_callback(VariableItem* item) { static void subbrute_scene_setup_extra_init_var_list(SubBruteState* instance, bool on_extra) { furi_assert(instance); - char str[6]; + char str[6] = {0}; VariableItem* item; static bool extra = false; if(on_extra) { @@ -254,7 +254,7 @@ static void subbrute_scene_setup_extra_init_var_list(SubBruteState* instance, bo static void setup_extra_enter_callback(void* context, uint32_t index) { furi_assert(context); - SubBruteState* instance = context; + SubBruteState* instance = (SubBruteState*)context; if(index == SubBruteVarListIndexRepeatOrOnExtra) { subbrute_scene_setup_extra_init_var_list(instance, true); @@ -263,14 +263,14 @@ static void setup_extra_enter_callback(void* context, uint32_t index) { void subbrute_scene_setup_extra_on_enter(void* context) { furi_assert(context); - SubBruteState* instance = context; + SubBruteState* instance = (SubBruteState*)context; subbrute_scene_setup_extra_init_var_list(instance, false); } void subbrute_scene_setup_extra_on_exit(void* context) { furi_assert(context); - SubBruteState* instance = context; + SubBruteState* instance = (SubBruteState*)context; variable_item_list_reset(instance->var_list); } diff --git a/subbrute_device.c b/subbrute_device.c index 5670e26a606..ec854d63218 100644 --- a/subbrute_device.c +++ b/subbrute_device.c @@ -21,11 +21,8 @@ SubBruteDevice* subbrute_device_alloc(const SubGhzDevice* radio_device) { instance->radio_device = radio_device; -//#ifdef FURI_DEBUG -// subbrute_device_attack_set_default_values(instance, SubBruteAttackLoadFile); -//#else subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433); -//#endif + return instance; } diff --git a/subbrute_i.h b/subbrute_i.h index eb90bef9fa5..573d335aab1 100644 --- a/subbrute_i.h +++ b/subbrute_i.h @@ -31,7 +31,7 @@ #include "views/subbrute_attack_view.h" #include "views/subbrute_main_view.h" -#define SUBBRUTEFORCER_VER "Sub-GHz BruteForcer 3.B" +#define SUBBRUTEFORCER_VER "Sub-GHz BruteForcer 3.C" #ifdef FURI_DEBUG //#define SUBBRUTE_FAST_TRACK false diff --git a/subbrute_protocols.c b/subbrute_protocols.c index 8ca5bb51869..8c69b2fb58d 100644 --- a/subbrute_protocols.c +++ b/subbrute_protocols.c @@ -146,6 +146,17 @@ const SubBruteProtocol subbrute_protocol_chamberlain_9bit_315 = { .preset = FuriHalSubGhzPresetOok650Async, .file = ChamberlainFileProtocol}; +/** + * Chamberlain 9bit 318MHz + */ +const SubBruteProtocol subbrute_protocol_chamberlain_9bit_318 = { + .frequency = 318000000, + .bits = 9, + .te = 0, + .repeat = 3, + .preset = FuriHalSubGhzPresetOok650Async, + .file = ChamberlainFileProtocol}; + /** * Chamberlain 9bit 390MHz */ @@ -435,6 +446,7 @@ static const char* subbrute_protocol_names[] = { [SubBruteAttackHoltek12bitAM915] = "Holtek AM 12bit 915MHz", [SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz", [SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz", + [SubBruteAttackChamberlain9bit318] = "Chamberlain 9bit 318MHz", [SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz", [SubBruteAttackChamberlain9bit433] = "Chamberlain 9bit 433MHz", [SubBruteAttackChamberlain8bit300] = "Chamberlain 8bit 300MHz", @@ -487,6 +499,7 @@ const SubBruteProtocol* subbrute_protocol_registry[] = { [SubBruteAttackHoltek12bitAM915] = &subbrute_protocol_holtek_12bit_am_915, [SubBruteAttackChamberlain9bit300] = &subbrute_protocol_chamberlain_9bit_300, [SubBruteAttackChamberlain9bit315] = &subbrute_protocol_chamberlain_9bit_315, + [SubBruteAttackChamberlain9bit318] = &subbrute_protocol_chamberlain_9bit_318, [SubBruteAttackChamberlain9bit390] = &subbrute_protocol_chamberlain_9bit_390, [SubBruteAttackChamberlain9bit433] = &subbrute_protocol_chamberlain_9bit_433, [SubBruteAttackChamberlain8bit300] = &subbrute_protocol_chamberlain_8bit_300, @@ -828,8 +841,6 @@ void subbrute_protocol_file_generate_file( uint64_t file_key, bool two_bytes) { FuriString* candidate = furi_string_alloc(); - // char subbrute_payload_byte[8]; - //furi_string_set_str(candidate, file_key); subbrute_protocol_create_candidate_for_existing_file( candidate, step, bit_index, file_key, two_bytes); diff --git a/subbrute_protocols.h b/subbrute_protocols.h index 07bfbebedbf..2ddd5797aa9 100644 --- a/subbrute_protocols.h +++ b/subbrute_protocols.h @@ -90,6 +90,7 @@ typedef enum { * - `SubBruteAttackHoltek12bitAM915`: Holtek 12-bit AM 915 MHz sub-brute attack. * - `SubBruteAttackChamberlain9bit300`: Chamberlain 9-bit 300 MHz sub-brute attack. * - `SubBruteAttackChamberlain9bit315`: Chamberlain 9-bit 315 MHz sub-brute attack. + * - `SubBruteAttackChamberlain9bit318`: Chamberlain 9-bit 318 MHz sub-brute attack. * - `SubBruteAttackChamberlain9bit390`: Chamberlain 9-bit 390 MHz sub-brute attack. * - `SubBruteAttackChamberlain9bit433`: Chamberlain 9-bit 433 MHz sub-brute attack. * - `SubBruteAttackChamberlain8bit300`: Chamberlain 8-bit 300 MHz sub-brute attack. @@ -131,6 +132,7 @@ typedef enum { SubBruteAttackHoltek12bitAM915, SubBruteAttackChamberlain9bit300, SubBruteAttackChamberlain9bit315, + SubBruteAttackChamberlain9bit318, SubBruteAttackChamberlain9bit390, SubBruteAttackChamberlain9bit433, SubBruteAttackChamberlain8bit300, diff --git a/views/subbrute_attack_view.c b/views/subbrute_attack_view.c index a49ffcbddc8..5678fcf93f5 100644 --- a/views/subbrute_attack_view.c +++ b/views/subbrute_attack_view.c @@ -193,9 +193,7 @@ View* subbrute_attack_view_get_view(SubBruteAttackView* instance) { void subbrute_attack_view_set_current_step(SubBruteAttackView* instance, uint64_t current_step) { furi_assert(instance); -#ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "Set step: %d", current_step); -#endif + instance->current_step = current_step; with_view_model( instance->view, @@ -226,7 +224,6 @@ void subbrute_attack_view_init_values( instance->max_value = max_value; instance->current_step = current_step; instance->is_attacking = is_attacking; - // instance->extra_repeats = extra_repeats; with_view_model( instance->view, @@ -262,7 +259,7 @@ void subbrute_attack_view_exit(void* context) { void subbrute_attack_view_draw(Canvas* canvas, void* context) { furi_assert(context); SubBruteAttackViewModel* model = (SubBruteAttackViewModel*)context; - char buffer[64]; + char buffer[64] = {0}; const char* attack_name = NULL; attack_name = subbrute_protocol_name(model->attack_type); diff --git a/views/subbrute_main_view.c b/views/subbrute_main_view.c index de40670b6d7..354340c56c2 100644 --- a/views/subbrute_main_view.c +++ b/views/subbrute_main_view.c @@ -109,9 +109,6 @@ void subbrute_main_view_center_displayed_key( } void subbrute_main_view_draw_is_byte_selected(Canvas* canvas, SubBruteMainViewModel* model) { -#ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "key_from_file: %s", model->key_from_file); -#endif canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned( canvas, 64, 17, AlignCenter, AlignTop, "Please select values to calc:"); @@ -152,9 +149,6 @@ void subbrute_main_view_draw_is_ordinary_selected(Canvas* canvas, SubBruteMainVi const uint8_t item_height = 16; const uint8_t string_height_offset = 9; -#ifdef FURI_DEBUG - //FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, model->index); -#endif for(size_t position = 0; position < SubBruteAttackTotalCount; ++position) { uint8_t item_position = position - model->window_position; @@ -189,7 +183,7 @@ void subbrute_main_view_draw_is_ordinary_selected(Canvas* canvas, SubBruteMainVi #else canvas_set_font(canvas, FontBatteryPercent); #endif - char buffer[10]; + char buffer[10] = {0}; snprintf(buffer, sizeof(buffer), "x%d", current_repeat_count); uint8_t temp_x_offset_repeats = current_repeat_count <= SUBBRUTE_PROTOCOL_MAX_REPEATS ? 15 : 18; @@ -230,11 +224,13 @@ bool subbrute_main_view_input_file_protocol(InputEvent* event, SubBruteMainView* (instance->two_bytes && instance->index > 1)) { instance->index--; } + updated = true; } else if(event->key == InputKeyRight) { if(instance->index < 7) { instance->index++; } + updated = true; } else if(event->key == InputKeyUp) { instance->two_bytes = !instance->two_bytes; @@ -242,14 +238,12 @@ bool subbrute_main_view_input_file_protocol(InputEvent* event, SubBruteMainView* if(instance->two_bytes && instance->index < 7) { instance->index++; } - // instance->callback( - // instance->two_bytes ? SubBruteCustomEventTypeChangeStepUp : - // SubBruteCustomEventTypeChangeStepDown, - // instance->context); updated = true; } else if(event->key == InputKeyOk) { - instance->callback(SubBruteCustomEventTypeIndexSelected, instance->context); + instance->callback(SubBruteCustomEventTypeIndexSelected, + instance->context); + updated = true; } return updated; @@ -259,6 +253,7 @@ bool subbrute_main_view_input_ordinary_protocol( InputEvent* event, SubBruteMainView* instance, bool is_short) { + const uint8_t min_value = 0; const uint8_t correct_total = SubBruteAttackTotalCount - 1; uint8_t index = instance->index; @@ -273,7 +268,7 @@ bool subbrute_main_view_input_ordinary_protocol( } else { instance->index = CLAMP(index - 1, correct_total, min_value); } - //instance->repeat_values = 0; + updated = true; } else if(event->key == InputKeyDown && is_short) { if(index == correct_total) { @@ -281,7 +276,7 @@ bool subbrute_main_view_input_ordinary_protocol( } else { instance->index = CLAMP(index + 1, correct_total, min_value); } - //instance->repeat_values = 0; + updated = true; } else if(event->key == InputKeyLeft && is_short) { instance->repeat_values[index] = CLAMP(current_repeats - 1, max_repeats, min_repeats); @@ -297,6 +292,7 @@ bool subbrute_main_view_input_ordinary_protocol( } else { instance->callback(SubBruteCustomEventTypeMenuSelected, instance->context); } + updated = true; } @@ -322,7 +318,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); - SubBruteMainView* instance = context; + SubBruteMainView* instance = (SubBruteMainView*)context; if(event->key == InputKeyBack && event->type == InputTypeShort) { #ifdef FURI_DEBUG @@ -417,6 +413,7 @@ void subbrute_main_view_free(SubBruteMainView* instance) { View* subbrute_main_view_get_view(SubBruteMainView* instance) { furi_assert(instance); + return instance->view; } @@ -427,6 +424,7 @@ void subbrute_main_view_set_index( bool is_select_byte, bool two_bytes, uint64_t key_from_file) { + furi_assert(instance); furi_assert(idx < SubBruteAttackTotalCount); #ifdef FURI_DEBUG @@ -460,6 +458,7 @@ void subbrute_main_view_set_index( model->key_from_file = instance->key_from_file; model->is_select_byte = instance->is_select_byte; model->two_bytes = instance->two_bytes; + for(size_t i = 0; i < SubBruteAttackTotalCount; i++) { model->repeat_values[i] = repeats[i]; } @@ -469,15 +468,18 @@ void subbrute_main_view_set_index( SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance) { furi_assert(instance); + return instance->index; } const uint8_t* subbrute_main_view_get_repeats(SubBruteMainView* instance) { furi_assert(instance); + return instance->repeat_values; } bool subbrute_main_view_get_two_bytes(SubBruteMainView* instance) { furi_assert(instance); + return instance->two_bytes; }