This commit is contained in:
RogueMaster
2022-12-02 17:01:50 -05:00
parent 7a5596358a
commit cf03e952a5
21 changed files with 615 additions and 318 deletions

View File

@@ -2,13 +2,34 @@
SubGhz Bruteforcer from [Unleashed Firmware](https://github.com/DarkFlippers/unleashed-firmware)
### Disclaimer
This software is for experimental purposes only and is not meant for any illegal activity/purposes.
We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law.
### Supported Protocols:
#### CAME
- CAME 12bit 303MHz
- CAME 12bit 307MHz
- CAME 12bit 315MHz
- CAME 12bit 433MHz
- CAME 12bit 868MHz
#### NICE
- NICE 12bit 433MHz
- NICE 12bit 868MHz
#### Ansonic
- Ansonic 12bit 433.075MHz
- Ansonic 12bit 433.920MHz
- Ansonic 12bit 434.075MHz
#### Chamberlain
- Chamberlain 9bit 300MHz
- Chamberlain 9bit 315MHz
- Chamberlain 9bit 390MHz
@@ -19,6 +40,12 @@ SubGhz Bruteforcer from [Unleashed Firmware](https://github.com/DarkFlippers/unl
- Chamberlain 7bit 300MHz
- Chamberlain 7bit 315MHz
- Chamberlain 7bit 390MHz
#### Linear
- Linear 10bit 300MHz
- Linear 10bit 310MHz
- BF Existing dump works for all other static protocols supported by Flipper Zero
#### Additional
- BF Existing dump works for all other static protocols supported by Flipper Zero

View File

@@ -7,7 +7,7 @@ App(
requires=["gui","dialogs"],
stack_size=2 * 1024,
order=11,
fap_icon="subbrute_10px.png",
fap_icon="images/subbrute_10px.png",
fap_category="Tools",
fap_icon_assets="images",
)

View File

@@ -0,0 +1,59 @@
#include "gui_top_buttons.h"
void elements_button_top_left(Canvas* canvas, const char* str) {
const Icon* icon = &I_ButtonUp_7x4;
const uint8_t button_height = 12;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 3;
const uint8_t string_width = canvas_string_width(canvas, str);
const uint8_t icon_h_offset = 3;
const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset;
const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset;
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
const uint8_t x = 0;
const uint8_t y = 0 + button_height;
uint8_t line_x = x + button_width;
uint8_t line_y = y - button_height;
canvas_draw_box(canvas, x, line_y, button_width, button_height);
canvas_draw_line(canvas, line_x + 0, line_y, line_x + 0, y - 1);
canvas_draw_line(canvas, line_x + 1, line_y, line_x + 1, y - 2);
canvas_draw_line(canvas, line_x + 2, line_y, line_x + 2, y - 3);
canvas_invert_color(canvas);
canvas_draw_icon(canvas, x + horizontal_offset, y - icon_v_offset, icon);
canvas_draw_str(
canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str);
canvas_invert_color(canvas);
}
void elements_button_top_right(Canvas* canvas, const char* str) {
const Icon* icon = &I_ButtonDown_7x4;
const uint8_t button_height = 12;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 3;
const uint8_t string_width = canvas_string_width(canvas, str);
const uint8_t icon_h_offset = 3;
const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset;
const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset + 1;
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
const uint8_t x = canvas_width(canvas);
const uint8_t y = 0 + button_height;
uint8_t line_x = x - button_width;
uint8_t line_y = y - button_height;
canvas_draw_box(canvas, line_x, line_y, button_width, button_height);
canvas_draw_line(canvas, line_x - 1, line_y, line_x - 1, y - 1);
canvas_draw_line(canvas, line_x - 2, line_y, line_x - 2, y - 2);
canvas_draw_line(canvas, line_x - 3, line_y, line_x - 3, y - 3);
canvas_invert_color(canvas);
canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str);
canvas_draw_icon(
canvas, x - horizontal_offset - icon_get_width(icon), y - icon_v_offset, icon);
canvas_invert_color(canvas);
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <input/input.h>
#include <gui/elements.h>
#include <gui/icon.h>
#include <gui/icon_animation.h>
#include <assets_icons.h>
/**
* Thanks to the author of metronome
* @param canvas
* @param str
*/
void elements_button_top_left(Canvas* canvas, const char* str);
/**
* Thanks to the author of metronome
* @param canvas
* @param str
*/
void elements_button_top_right(Canvas* canvas, const char* str);

View File

@@ -96,8 +96,11 @@ bool subbrute_worker_init_default_attack(
instance->te = protocol->te;
instance->repeat = protocol->repeat + extra_repeats;
instance->load_index = 0;
instance->file_key = NULL;
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
instance->file_key = 0;
instance->two_bytes = false;
instance->max_value =
subbrute_protocol_calc_max_value(instance->attack, instance->bits, instance->two_bytes);
instance->initiated = true;
instance->state = SubBruteWorkerStateReady;
@@ -122,9 +125,10 @@ bool subbrute_worker_init_file_attack(
SubBruteWorker* instance,
uint64_t step,
uint8_t load_index,
const char* file_key,
uint64_t file_key,
SubBruteProtocol* protocol,
uint8_t extra_repeats) {
uint8_t extra_repeats,
bool two_bytes) {
furi_assert(instance);
if(instance->worker_running) {
@@ -142,7 +146,10 @@ bool subbrute_worker_init_file_attack(
instance->load_index = load_index;
instance->repeat = protocol->repeat + extra_repeats;
instance->file_key = file_key;
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
instance->two_bytes = two_bytes;
instance->max_value =
subbrute_protocol_calc_max_value(instance->attack, instance->bits, instance->two_bytes);
instance->initiated = true;
instance->state = SubBruteWorkerStateReady;
@@ -150,14 +157,15 @@ bool subbrute_worker_init_file_attack(
#ifdef FURI_DEBUG
FURI_LOG_I(
TAG,
"subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
"subbrute_worker_init_file_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld, key: %llX",
subbrute_protocol_name(instance->attack),
instance->bits,
subbrute_protocol_preset(instance->preset),
subbrute_protocol_file(instance->file),
instance->te,
instance->repeat,
instance->max_value);
instance->max_value,
instance->file_key);
#endif
return true;
@@ -244,7 +252,8 @@ bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t ste
instance->te,
instance->repeat,
instance->load_index,
instance->file_key);
instance->file_key,
instance->two_bytes);
} else {
subbrute_protocol_default_payload(
stream, step, instance->bits, instance->te, instance->repeat);
@@ -373,7 +382,8 @@ int32_t subbrute_worker_thread(void* context) {
instance->te,
instance->repeat,
instance->load_index,
instance->file_key);
instance->file_key,
instance->two_bytes);
} else {
subbrute_protocol_default_payload(
stream, instance->step, instance->bits, instance->te, instance->repeat);

View File

@@ -28,9 +28,10 @@ bool subbrute_worker_init_file_attack(
SubBruteWorker* instance,
uint64_t step,
uint8_t load_index,
const char* file_key,
uint64_t file_key,
SubBruteProtocol* protocol,
uint8_t extra_repeats);
uint8_t extra_repeats,
bool two_bytes);
bool subbrute_worker_start(SubBruteWorker* instance);
void subbrute_worker_stop(SubBruteWorker* instance);
bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step);

View File

@@ -31,8 +31,9 @@ struct SubBruteWorker {
uint8_t te;
uint8_t repeat;
uint8_t load_index; // Index of group to bruteforce in loaded file
const char* file_key;
uint64_t file_key;
uint64_t max_value; // Max step
bool two_bytes;
// Manual transmit
uint32_t last_time_tx_data;

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -3,13 +3,6 @@
#define TAG "SubBruteSceneLoadFile"
//void subbrute_scene_load_file_callback(SubBruteCustomEvent event, void* context) {
//// furi_assert(context);
////
//// SubBruteState* instance = (SubBruteState*)context;
//// view_dispatcher_send_custom_event(instance->view_dispatcher, event);
//}
void subbrute_scene_load_file_on_enter(void* context) {
furi_assert(context);
SubBruteState* instance = (SubBruteState*)context;
@@ -24,8 +17,14 @@ void subbrute_scene_load_file_on_enter(void* context) {
dialog_file_browser_set_basic_options(&browser_options, SUBBRUTE_FILE_EXT, &I_sub1_10px);
SubBruteFileResult load_result = SubBruteFileResultUnknown;
// TODO: DELETE IT
#ifdef SUBBRUTE_FAST_TRACK
bool res = true;
furi_string_printf(load_path, "%s", "/ext/subghz/princeton.sub");
#else
bool res =
dialog_file_browser_show(instance->dialogs, load_path, app_folder, &browser_options);
#endif
#ifdef FURI_DEBUG
FURI_LOG_D(
TAG,
@@ -44,11 +43,12 @@ void subbrute_scene_load_file_on_enter(void* context) {
if(load_result == SubBruteFileResultOk) {
if(!subbrute_worker_init_file_attack(
instance->worker,
instance->device->key_index,
instance->device->load_index,
instance->device->file_key,
instance->device->current_step,
instance->device->bit_index,
instance->device->key_from_file,
instance->device->file_protocol_info,
extra_repeats)) {
extra_repeats,
instance->device->two_bytes)) {
furi_crash("Invalid attack set!");
}
// Ready to run!

View File

@@ -20,7 +20,8 @@ void subbrute_scene_load_select_on_enter(void* context) {
instance->current_view = SubBruteViewMain;
subbrute_main_view_set_callback(view, subbrute_scene_load_select_callback, instance);
subbrute_main_view_set_index(view, 7, true, instance->device->file_key);
subbrute_main_view_set_index(
view, 7, true, instance->device->two_bytes, instance->device->key_from_file);
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
}
@@ -38,21 +39,37 @@ bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event)
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubBruteCustomEventTypeIndexSelected) {
instance->device->load_index = subbrute_main_view_get_index(instance->view_main);
/*#ifdef FURI_DEBUG && !SUBBRUTE_FAST_TRACK
view_dispatcher_stop(instance->view_dispatcher);
consumed = true;
#else*/
instance->device->current_step = 0;
instance->device->bit_index = subbrute_main_view_get_index(instance->view_main);
instance->device->two_bytes = subbrute_main_view_get_two_bytes(instance->view_main);
uint8_t extra_repeats = subbrute_main_view_get_extra_repeats(instance->view_main);
instance->device->max_value = subbrute_protocol_calc_max_value(
instance->device->attack,
instance->device->bit_index,
instance->device->two_bytes);
if(!subbrute_worker_init_file_attack(
instance->worker,
instance->device->key_index,
instance->device->load_index,
instance->device->file_key,
instance->device->current_step,
instance->device->bit_index,
instance->device->key_from_file,
instance->device->file_protocol_info,
extra_repeats)) {
extra_repeats,
instance->device->two_bytes)) {
furi_crash("Invalid attack set!");
}
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
/*#endif*/
consumed = true;
}
} /* else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
instance->device->two_bytes = true;
} else if(event.event == SubBruteCustomEventTypeChangeStepDown) {
instance->device->two_bytes = false;
}*/
} else if(event.type == SceneManagerEventTypeBack) {
if(!scene_manager_search_and_switch_to_previous_scene(
instance->scene_manager, SubBruteSceneStart)) {

View File

@@ -45,7 +45,7 @@ void subbrute_scene_run_attack_on_enter(void* context) {
instance->worker, subbrute_scene_run_attack_device_state_changed, instance);
if(!subbrute_worker_is_running(instance->worker)) {
subbrute_worker_set_step(instance->worker, instance->device->key_index);
subbrute_worker_set_step(instance->worker, instance->device->current_step);
if(!subbrute_worker_start(instance->worker)) {
view_dispatcher_send_custom_event(
instance->view_dispatcher, SubBruteCustomEventTypeError);
@@ -64,7 +64,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
if(event.type == SceneManagerEventTypeCustom) {
uint64_t step = subbrute_worker_get_step(instance->worker);
instance->device->key_index = step;
instance->device->current_step = step;
subbrute_attack_view_set_current_step(view, step);
if(event.event == SubBruteCustomEventTypeTransmitFinished) {
@@ -89,12 +89,12 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
scene_manager_search_and_switch_to_previous_scene(
instance->scene_manager, SubBruteSceneSetupAttack);
} else if(event.event == SubBruteCustomEventTypeUpdateView) {
//subbrute_attack_view_set_current_step(view, instance->device->key_index);
//subbrute_attack_view_set_current_step(view, instance->device->current_step);
}
consumed = true;
} else if(event.type == SceneManagerEventTypeTick) {
uint64_t step = subbrute_worker_get_step(instance->worker);
instance->device->key_index = step;
instance->device->current_step = step;
subbrute_attack_view_set_current_step(view, step);
consumed = true;

View File

@@ -37,14 +37,14 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
instance->worker, subbrute_scene_setup_attack_device_state_changed, context);
if(subbrute_worker_is_running(instance->worker)) {
subbrute_worker_stop(instance->worker);
instance->device->key_index = subbrute_worker_get_step(instance->worker);
instance->device->current_step = subbrute_worker_get_step(instance->worker);
}
subbrute_attack_view_init_values(
view,
instance->device->attack,
instance->device->max_value,
instance->device->key_index,
instance->device->current_step,
false,
instance->device->extra_repeats);
@@ -77,7 +77,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
view,
instance->device->attack,
instance->device->max_value,
instance->device->key_index,
instance->device->current_step,
false,
instance->device->extra_repeats);
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
@@ -86,7 +86,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
view,
instance->device->attack,
instance->device->max_value,
instance->device->key_index,
instance->device->current_step,
false,
instance->device->extra_repeats);
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
@@ -99,7 +99,7 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
// Blink
notification_message(instance->notifications, &sequence_blink_green_100);
subbrute_worker_transmit_current_key(
instance->worker, instance->device->key_index);
instance->worker, instance->device->current_step);
// Stop
notification_message(instance->notifications, &sequence_blink_stop);
}
@@ -128,9 +128,9 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
consumed = true;
} else if(event.type == SceneManagerEventTypeTick) {
if(subbrute_worker_is_running(instance->worker)) {
instance->device->key_index = subbrute_worker_get_step(instance->worker);
instance->device->current_step = subbrute_worker_get_step(instance->worker);
}
subbrute_attack_view_set_current_step(view, instance->device->key_index);
subbrute_attack_view_set_current_step(view, instance->device->current_step);
consumed = true;
}

View File

@@ -23,9 +23,14 @@ void subbrute_scene_start_on_enter(void* context) {
instance->current_view = SubBruteViewMain;
subbrute_main_view_set_callback(view, subbrute_scene_start_callback, instance);
subbrute_main_view_set_index(view, instance->device->attack, false, NULL);
subbrute_main_view_set_index(view, instance->device->attack, false, instance->device->two_bytes, 0);
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
// TODO: DELETE IT
#ifdef SUBBRUTE_FAST_TRACK
scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile);
#endif
}
void subbrute_scene_start_on_exit(void* context) {
@@ -57,7 +62,7 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) {
(!subbrute_worker_init_default_attack(
instance->worker,
attack,
instance->device->key_index,
instance->device->current_step,
instance->device->protocol_info,
instance->device->extra_repeats))) {
furi_crash("Invalid attack set!");

View File

@@ -12,7 +12,7 @@
SubBruteDevice* subbrute_device_alloc() {
SubBruteDevice* instance = malloc(sizeof(SubBruteDevice));
instance->key_index = 0;
instance->current_step = 0;
instance->protocol_info = NULL;
instance->file_protocol_info = NULL;
@@ -23,7 +23,7 @@ SubBruteDevice* subbrute_device_alloc() {
instance->environment, (void*)&subghz_protocol_registry);
#ifdef FURI_DEBUG
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433);
subbrute_device_attack_set_default_values(instance, SubBruteAttackLoadFile);
#else
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433);
#endif
@@ -51,32 +51,32 @@ void subbrute_device_free(SubBruteDevice* instance) {
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
if(step > 0) {
if((instance->key_index + step) - instance->max_value == 1) {
instance->key_index = 0x00;
if((instance->current_step + step) - instance->max_value == 1) {
instance->current_step = 0x00;
} else {
uint64_t value = instance->key_index + step;
uint64_t value = instance->current_step + step;
if(value == instance->max_value) {
instance->key_index = value;
instance->current_step = value;
} else {
instance->key_index = value % instance->max_value;
instance->current_step = value % instance->max_value;
}
}
} else {
if(instance->key_index + step == 0) {
instance->key_index = 0x00;
} else if(instance->key_index == 0) {
instance->key_index = instance->max_value;
if(instance->current_step + step == 0) {
instance->current_step = 0x00;
} else if(instance->current_step == 0) {
instance->current_step = instance->max_value;
} else {
uint64_t value = ((instance->key_index + step) + instance->max_value);
uint64_t value = ((instance->current_step + step) + instance->max_value);
if(value == instance->max_value) {
instance->key_index = value;
instance->current_step = value;
} else {
instance->key_index = value % instance->max_value;
instance->current_step = value % instance->max_value;
}
}
}
return instance->key_index;
return instance->current_step;
}
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
@@ -101,19 +101,20 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
instance->file_protocol_info->frequency,
instance->file_protocol_info->preset,
instance->file_protocol_info->file,
instance->key_index,
instance->current_step,
instance->file_protocol_info->bits,
instance->file_protocol_info->te,
instance->file_protocol_info->repeat,
instance->load_index,
instance->file_key);
instance->bit_index,
instance->key_from_file,
instance->two_bytes);
} else {
subbrute_protocol_default_generate_file(
stream,
instance->protocol_info->frequency,
instance->protocol_info->preset,
instance->protocol_info->file,
instance->key_index,
instance->current_step,
instance->protocol_info->bits,
instance->protocol_info->te,
instance->protocol_info->repeat);
@@ -174,8 +175,8 @@ SubBruteFileResult subbrute_device_attack_set(
protocol_check_result = SubBruteFileResultOk;
// Calc max value
instance->max_value =
subbrute_protocol_calc_max_value(instance->attack, instance->protocol_info->bits);
instance->max_value = subbrute_protocol_calc_max_value(
instance->attack, instance->protocol_info->bits, instance->two_bytes);
}
#ifdef FURI_DEBUG
bits = instance->protocol_info->bits;
@@ -189,8 +190,8 @@ SubBruteFileResult subbrute_device_attack_set(
protocol_check_result = SubBruteFileResultOk;
// Calc max value
instance->max_value =
subbrute_protocol_calc_max_value(instance->attack, instance->file_protocol_info->bits);
instance->max_value = subbrute_protocol_calc_max_value(
instance->attack, instance->file_protocol_info->bits, instance->two_bytes);
#ifdef FURI_DEBUG
bits = instance->file_protocol_info->bits;
te = instance->file_protocol_info->te;
@@ -257,25 +258,24 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
}
// Frequency
if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
instance->file_protocol_info->frequency = temp_data32;
if(!furi_hal_subghz_is_tx_allowed(instance->file_protocol_info->frequency)) {
result = SubBruteFileResultFrequencyNotAllowed;
break;
}
} else {
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
FURI_LOG_E(TAG, "Missing or incorrect Frequency");
result = SubBruteFileResultMissingOrIncorrectFrequency;
break;
}
instance->file_protocol_info->frequency = temp_data32;
if(!furi_hal_subghz_is_tx_allowed(instance->file_protocol_info->frequency)) {
result = SubBruteFileResultFrequencyNotAllowed;
break;
}
// Preset
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
FURI_LOG_E(TAG, "Preset FAIL");
result = SubBruteFileResultPresetInvalid;
} else {
instance->file_protocol_info->preset = subbrute_protocol_convert_preset(temp_str);
break;
}
instance->file_protocol_info->preset = subbrute_protocol_convert_preset(temp_str);
const char* protocol_file = NULL;
// Protocol
@@ -283,13 +283,12 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
FURI_LOG_E(TAG, "Missing Protocol");
result = SubBruteFileResultMissingProtocol;
break;
} else {
instance->file_protocol_info->file = subbrute_protocol_file_protocol_name(temp_str);
protocol_file = subbrute_protocol_file(instance->file_protocol_info->file);
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Protocol: %s", protocol_file);
#endif
}
instance->file_protocol_info->file = subbrute_protocol_file_protocol_name(temp_str);
protocol_file = subbrute_protocol_file(instance->file_protocol_info->file);
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Protocol: %s", protocol_file);
#endif
instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
instance->receiver, furi_string_get_cstr(temp_str));
@@ -307,9 +306,7 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
break;
}
#ifdef FURI_DEBUG
else {
FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name);
}
FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name);
#endif
// Bit
@@ -317,28 +314,120 @@ uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* fil
FURI_LOG_E(TAG, "Missing or incorrect Bit");
result = SubBruteFileResultMissingOrIncorrectBit;
break;
} else {
instance->file_protocol_info->bits = temp_data32;
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Bit: %d", instance->file_protocol_info->bits);
#endif
}
instance->file_protocol_info->bits = temp_data32;
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Bit: %d", instance->file_protocol_info->bits);
#endif
// TODO: Delete this
// Key
if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) {
FURI_LOG_E(TAG, "Missing or incorrect Key");
// if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) {
// FURI_LOG_E(TAG, "Missing or incorrect Key");
// result = SubBruteFileResultMissingOrIncorrectKey;
// break;
// } else {
// snprintf(
// instance->current_key_from_file,
// sizeof(instance->current_key_from_file),
// "%s",
// furi_string_get_cstr(temp_str));
// #ifdef FURI_DEBUG
// FURI_LOG_D(TAG, "Key: %s", instance->current_key_from_file);
// #endif
// }
//
// flipper_format_rewind(fff_data_file);
uint8_t key_data[sizeof(uint64_t)] = {0};
if(!flipper_format_read_hex(fff_data_file, "Key", key_data, sizeof(uint64_t))) {
FURI_LOG_E(TAG, "Missing Key");
result = SubBruteFileResultMissingOrIncorrectKey;
break;
} else {
snprintf(
instance->file_key,
sizeof(instance->file_key),
"%s",
furi_string_get_cstr(temp_str));
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "Key: %s", instance->file_key);
#endif
}
uint64_t data = 0;
for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
data = (data << 8) | key_data[i];
}
#if FURI_DEBUG
FURI_LOG_D(TAG, "Key: %.16llX", data);
#endif
instance->key_from_file = data;
// uint16_t add_value = 0x0001;
// uint8_t bit_index = 7;
// bool two_bytes = true;
// uint8_t p[8];
// for(int i = 0; i < 8; i++) {
// p[i] = (uint8_t)(instance->key_from_file >> 8 * (7 - i)) & 0xFF;
// }
// uint16_t num = two_bytes ? (p[bit_index - 1] << 8) | p[bit_index] : p[bit_index];
// FURI_LOG_D(TAG, "num: 0x%04X", num);
// num += add_value;
// FURI_LOG_D(TAG, "num added: 0x%04X", num);
// uint8_t low_byte = num & (0xff);
// uint8_t high_byte = (num >> 8) & 0xff;
// data = 0;
// for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
// if(i == bit_index - 1 && two_bytes) {
// data = (data << 8) | high_byte;
// data = (data << 8) | low_byte;
// i++;
// } else if(i == bit_index) {
// data = (data << 8) | low_byte;
// } else {
// data = (data << 8) | p[i];
// }
// }
// #if FURI_DEBUG
// furi_string_printf(temp_str, "Key: %lX", (uint32_t)(data & 0xFFFFFFFF));
// FURI_LOG_D(
// TAG, "H: 0x%02X, L: 0x%02X, %s", high_byte, low_byte, furi_string_get_cstr(temp_str));
// #endif
// uint8_t key_data[sizeof(uint64_t)] = {0};
// if(!flipper_format_read_hex(fff_data_file, "Key", key_data, sizeof(uint64_t))) {
// FURI_LOG_E(TAG, "Missing Key");
// result = SubBruteFileResultMissingOrIncorrectKey;
// break;
// }
// uint64_t data = 0;
// for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
// data = (data << 8) | key_data[i];
// }
// instance->key_from_file = data;
// uint16_t add_value = 0x0001;
// uint8_t bit_index = 7;
// bool two_bytes = true;
// uint8_t p[8];
// for(int i = 0; i < 8; i++) {
// p[i] = (uint8_t)(instance->key_from_file >> 8 * (7 - i)) & 0xFF;
// }
// uint16_t num = two_bytes ? (p[bit_index - 1] << 8) | p[bit_index] : p[bit_index];
// FURI_LOG_D(TAG, "num: 0x%04X", num);
// num += add_value;
// FURI_LOG_D(TAG, "num added: 0x%04X", num);
// uint8_t low_byte = num & (0xff);
// uint8_t high_byte = (num >> 8) & 0xff;
// data = 0;
// for(uint8_t i = 0; i < sizeof(uint64_t); i++) {
// if(i == bit_index - 1 && two_bytes) {
// data = (data << 8) | high_byte;
// data = (data << 8) | low_byte;
// i++;
// } else if(i == bit_index) {
// data = (data << 8) | low_byte;
// } else {
// data = (data << 8) | p[i];
// }
// }
// furi_string_printf(temp_str, "Key: %lX", (uint32_t)(data & 0xFFFFFFFF));
// FURI_LOG_D(
// TAG, "H: 0x%02X, L: 0x%02X, %s", high_byte, low_byte, furi_string_get_cstr(temp_str));
// TE
if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) {
@@ -394,15 +483,15 @@ void subbrute_device_attack_set_default_values(
FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values");
#endif
instance->attack = default_attack;
instance->key_index = 0x00;
instance->load_index = 0x00;
instance->current_step = 0x00;
instance->bit_index = 0x00;
instance->extra_repeats = 0;
instance->two_bytes = false;
memset(instance->current_key, 0, sizeof(instance->current_key));
if(default_attack != SubBruteAttackLoadFile) {
memset(instance->file_key, 0, sizeof(instance->file_key));
instance->max_value = (uint64_t)0x00;
instance->max_value = subbrute_protocol_calc_max_value(
instance->attack, instance->bit_index, instance->two_bytes);
}
}

View File

@@ -36,9 +36,7 @@ typedef struct {
SubBruteProtocol* file_protocol_info;
// Current step
uint64_t key_index;
// Index of group to bruteforce in loaded file
uint8_t load_index;
uint64_t current_step;
// SubGhz
SubGhzReceiver* receiver;
@@ -52,7 +50,11 @@ typedef struct {
// Loaded info for attack type
char current_key[SUBBRUTE_PAYLOAD_SIZE];
char file_key[SUBBRUTE_MAX_LEN_NAME];
uint64_t key_from_file;
uint64_t current_key_from_file;
bool two_bytes;
// Index of group to bruteforce in loaded file
uint8_t bit_index;
} SubBruteDevice;
SubBruteDevice* subbrute_device_alloc();

View File

@@ -16,7 +16,7 @@
#include <gui/modules/widget.h>
#include <gui/modules/loading.h>
#include <SubGHz_Bruteforcer_icons.h>
#include "SubGHz_Bruteforcer_icons.h"
#include <dialogs/dialogs.h>
@@ -29,6 +29,10 @@
#include "views/subbrute_attack_view.h"
#include "views/subbrute_main_view.h"
#ifdef FURI_DEBUG
//#define SUBBRUTE_FAST_TRACK false
#endif
typedef enum {
SubBruteViewNone,
SubBruteViewMain,

View File

@@ -25,6 +25,17 @@ const SubBruteProtocol subbrute_protocol_came_12bit_307 = {
.preset = FuriHalSubGhzPresetOok650Async,
.file = CAMEFileProtocol};
/**
* CAME 12bit 315MHz
*/
const SubBruteProtocol subbrute_protocol_came_12bit_315 = {
.frequency = 315000000,
.bits = 12,
.te = 0,
.repeat = 3,
.preset = FuriHalSubGhzPresetOok650Async,
.file = CAMEFileProtocol};
/**
* CAME 12bit 433MHz
*/
@@ -243,6 +254,7 @@ const SubBruteProtocol subbrute_protocol_load_file =
static const char* subbrute_protocol_names[] = {
[SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz",
[SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz",
[SubBruteAttackCAME12bit315] = "CAME 12bit 315MHz",
[SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz",
[SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz",
[SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz",
@@ -279,6 +291,7 @@ static const char* subbrute_protocol_presets[] = {
const SubBruteProtocol* subbrute_protocol_registry[] = {
[SubBruteAttackCAME12bit303] = &subbrute_protocol_came_12bit_303,
[SubBruteAttackCAME12bit307] = &subbrute_protocol_came_12bit_307,
[SubBruteAttackCAME12bit315] = &subbrute_protocol_came_12bit_315,
[SubBruteAttackCAME12bit433] = &subbrute_protocol_came_12bit_433,
[SubBruteAttackCAME12bit868] = &subbrute_protocol_came_12bit_868,
[SubBruteAttackNICE12bit433] = &subbrute_protocol_nice_12bit_433,
@@ -366,27 +379,74 @@ SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) {
return UnknownFileProtocol;
}
void subbrute_protocol_create_candidate_for_existing_file(
FuriString* candidate,
uint64_t step,
uint8_t bit_index,
uint64_t file_key,
bool two_bytes) {
uint8_t p[8];
for(int i = 0; i < 8; i++) {
p[i] = (uint8_t)(file_key >> 8 * (7 - i)) & 0xFF;
}
uint8_t low_byte = step & (0xff);
uint8_t high_byte = (step >> 8) & 0xff;
size_t size = sizeof(uint64_t);
for(uint8_t i = 0; i < size; i++) {
if(i == bit_index - 1 && two_bytes) {
furi_string_cat_printf(candidate, "%02X %02X", high_byte, low_byte);
i++;
} else if(i == bit_index) {
furi_string_cat_printf(candidate, "%02X", low_byte);
} else if(p[i] != 0) {
furi_string_cat_printf(candidate, "%02X", p[i]);
} else {
furi_string_cat_printf(candidate, "%s", "00");
}
if(i < size - 1) {
furi_string_push_back(candidate, ' ');
}
}
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "file candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
#endif
}
void subbrute_protocol_create_candidate_for_default(FuriString* candidate, uint64_t step) {
uint8_t p[8];
for(int i = 0; i < 8; i++) {
p[i] = (uint8_t)(step >> 8 * (7 - i)) & 0xFF;
}
size_t size = sizeof(uint64_t);
for(uint8_t i = 0; i < size; i++) {
if(p[i] != 0) {
furi_string_cat_printf(candidate, "%02X", p[i]);
} else {
furi_string_cat_printf(candidate, "%s", "00");
}
if(i < size - 1) {
furi_string_push_back(candidate, ' ');
}
}
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
#endif
}
void subbrute_protocol_default_payload(
Stream* stream,
uint64_t step,
uint8_t bits,
uint8_t te,
uint8_t repeat) {
FuriString* candidate = furi_string_alloc_set_str(" ");
FuriString* buffer = furi_string_alloc_printf("%16llX", step);
int j = 0;
for(uint8_t i = 0; i < 16; i++) {
if(furi_string_get_char(buffer, i) != ' ') {
furi_string_set_char(candidate, i + j, furi_string_get_char(buffer, i));
} else {
furi_string_set_char(candidate, i + j, '0');
}
if(i % 2 != 0) {
j++;
}
}
furi_string_free(buffer);
FuriString* candidate = furi_string_alloc();
subbrute_protocol_create_candidate_for_default(candidate, step);
#ifdef FURI_DEBUG
FURI_LOG_D(
@@ -420,13 +480,12 @@ void subbrute_protocol_file_payload(
uint8_t bits,
uint8_t te,
uint8_t repeat,
uint8_t load_index,
const char* file_key) {
uint8_t bit_index,
uint64_t file_key,
bool two_bytes) {
FuriString* candidate = furi_string_alloc();
char subbrute_payload_byte[4];
furi_string_set_str(candidate, file_key);
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step);
furi_string_replace_at(candidate, load_index * 3, 3, subbrute_payload_byte);
subbrute_protocol_create_candidate_for_existing_file(
candidate, step, bit_index, file_key, two_bytes);
#ifdef FURI_DEBUG
FURI_LOG_D(
@@ -464,21 +523,8 @@ void subbrute_protocol_default_generate_file(
uint8_t bits,
uint8_t te,
uint8_t repeat) {
FuriString* candidate = furi_string_alloc_set_str(" ");
FuriString* buffer = furi_string_alloc_printf("%16llX", step);
int j = 0;
for(uint8_t i = 0; i < 16; i++) {
if(furi_string_get_char(buffer, i) != ' ') {
furi_string_set_char(candidate, i + j, furi_string_get_char(buffer, i));
} else {
furi_string_set_char(candidate, i + j, '0');
}
if(i % 2 != 0) {
j++;
}
}
furi_string_free(buffer);
FuriString* candidate = furi_string_alloc();
subbrute_protocol_create_candidate_for_default(candidate, step);
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
@@ -520,17 +566,15 @@ void subbrute_protocol_file_generate_file(
uint8_t bits,
uint8_t te,
uint8_t repeat,
uint8_t load_index,
const char* file_key) {
uint8_t bit_index,
uint64_t file_key,
bool two_bytes) {
FuriString* candidate = furi_string_alloc();
char subbrute_payload_byte[4];
furi_string_set_str(candidate, file_key);
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step);
furi_string_replace_at(candidate, load_index * 3, 3, subbrute_payload_byte);
// 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);
#ifdef FURI_DEBUG
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
#endif
stream_clean(stream);
if(te) {
stream_write_format(
@@ -558,10 +602,11 @@ void subbrute_protocol_file_generate_file(
furi_string_free(candidate);
}
uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) {
uint64_t
subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes) {
uint64_t max_value;
if(attack_type == SubBruteAttackLoadFile) {
max_value = 0xFF;
max_value = two_bytes ? 0xFFFF : 0xFF;
} else {
FuriString* max_value_s;
max_value_s = furi_string_alloc();

View File

@@ -26,6 +26,7 @@ typedef enum {
typedef enum {
SubBruteAttackCAME12bit303,
SubBruteAttackCAME12bit307,
SubBruteAttackCAME12bit315,
SubBruteAttackCAME12bit433,
SubBruteAttackCAME12bit868,
SubBruteAttackNICE12bit433,
@@ -78,8 +79,9 @@ void subbrute_protocol_file_payload(
uint8_t bits,
uint8_t te,
uint8_t repeat,
uint8_t load_index,
const char* file_key);
uint8_t bit_index,
uint64_t file_key,
bool two_bytes);
void subbrute_protocol_default_generate_file(
Stream* stream,
uint32_t frequency,
@@ -98,6 +100,8 @@ void subbrute_protocol_file_generate_file(
uint8_t bits,
uint8_t te,
uint8_t repeat,
uint8_t load_index,
const char* file_key);
uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits);
uint8_t bit_index,
uint64_t file_key,
bool two_bytes);
uint64_t
subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits, bool two_bytes);

View File

@@ -1,6 +1,7 @@
#include "subbrute_attack_view.h"
#include "../subbrute_i.h"
#include "../subbrute_protocols.h"
#include "../helpers/gui_top_buttons.h"
#include <input/input.h>
#include <gui/elements.h>
@@ -255,74 +256,6 @@ void subbrute_attack_view_exit(void* context) {
false);
}
/**
* Thanks to the author of metronome
* @param canvas
* @param str
*/
void elements_button_top_left(Canvas* canvas, const char* str) {
const Icon* icon = &I_ButtonUp_7x4;
const uint8_t button_height = 12;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 3;
const uint8_t string_width = canvas_string_width(canvas, str);
const uint8_t icon_h_offset = 3;
const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset;
const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset;
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
const uint8_t x = 0;
const uint8_t y = 0 + button_height;
uint8_t line_x = x + button_width;
uint8_t line_y = y - button_height;
canvas_draw_box(canvas, x, line_y, button_width, button_height);
canvas_draw_line(canvas, line_x + 0, line_y, line_x + 0, y - 1);
canvas_draw_line(canvas, line_x + 1, line_y, line_x + 1, y - 2);
canvas_draw_line(canvas, line_x + 2, line_y, line_x + 2, y - 3);
canvas_invert_color(canvas);
canvas_draw_icon(canvas, x + horizontal_offset, y - icon_v_offset, icon);
canvas_draw_str(
canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str);
canvas_invert_color(canvas);
}
/**
* Thanks to the author of metronome
* @param canvas
* @param str
*/
void elements_button_top_right(Canvas* canvas, const char* str) {
const Icon* icon = &I_ButtonDown_7x4;
const uint8_t button_height = 12;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 3;
const uint8_t string_width = canvas_string_width(canvas, str);
const uint8_t icon_h_offset = 3;
const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_h_offset;
const uint8_t icon_v_offset = icon_get_height(icon) + vertical_offset + 1;
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
const uint8_t x = canvas_width(canvas);
const uint8_t y = 0 + button_height;
uint8_t line_x = x - button_width;
uint8_t line_y = y - button_height;
canvas_draw_box(canvas, line_x, line_y, button_width, button_height);
canvas_draw_line(canvas, line_x - 1, line_y, line_x - 1, y - 1);
canvas_draw_line(canvas, line_x - 2, line_y, line_x - 2, y - 2);
canvas_draw_line(canvas, line_x - 3, line_y, line_x - 3, y - 3);
canvas_invert_color(canvas);
canvas_draw_str(canvas, x - button_width + horizontal_offset, y - vertical_offset, str);
canvas_draw_icon(
canvas, x - horizontal_offset - icon_get_width(icon), y - icon_v_offset, icon);
canvas_invert_color(canvas);
}
void subbrute_attack_view_draw(Canvas* canvas, void* context) {
furi_assert(context);
SubBruteAttackViewModel* model = (SubBruteAttackViewModel*)context;
@@ -339,9 +272,27 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) {
}
// Current Step / Max value
canvas_set_font(canvas, FontBigNumbers);
snprintf(buffer, sizeof(buffer), "%04d/%04d", (int)model->current_step, (int)model->max_value);
canvas_draw_str_aligned(canvas, 64, 17, AlignCenter, AlignTop, buffer);
const uint8_t y_frequency = 17;
if(model->max_value > 9999) {
canvas_set_font(canvas, FontBigNumbers);
snprintf(buffer, sizeof(buffer), "%05d/", (int)model->current_step);
canvas_draw_str_aligned(canvas, 5, y_frequency, AlignLeft, AlignTop, buffer);
// Second part with another font, because BigNumber is out of screen bounds
canvas_set_font(canvas, FontPrimary);
snprintf(buffer, sizeof(buffer), "%05d", (int)model->max_value);
canvas_draw_str_aligned(canvas, 107, y_frequency + 13, AlignRight, AlignBottom, buffer);
} else if(model->max_value <= 0xFF) {
canvas_set_font(canvas, FontBigNumbers);
snprintf(
buffer, sizeof(buffer), "%03d/%03d", (int)model->current_step, (int)model->max_value);
canvas_draw_str_aligned(canvas, 64, y_frequency, AlignCenter, AlignTop, buffer);
} else {
canvas_set_font(canvas, FontBigNumbers);
snprintf(
buffer, sizeof(buffer), "%04d/%04d", (int)model->current_step, (int)model->max_value);
canvas_draw_str_aligned(canvas, 64, y_frequency, AlignCenter, AlignTop, buffer);
}
canvas_set_font(canvas, FontSecondary);
memset(buffer, 0, sizeof(buffer));

View File

@@ -1,6 +1,7 @@
#include "subbrute_main_view.h"
#include "../subbrute_i.h"
#include "../subbrute_protocols.h"
#include "../helpers/gui_top_buttons.h"
#include <input/input.h>
#include <gui/elements.h>
@@ -10,6 +11,15 @@
#define TAG "SubBruteMainView"
#define ITEMS_ON_SCREEN 3
#define ITEMS_INTERVAL 1
#define ITEM_WIDTH 14
#define ITEM_Y 27
#define ITEM_HEIGHT 13
#define TEXT_X 6
#define TEXT_Y 37
#define TEXT_INTERVAL 3
#define TEXT_WIDTH 12
#define ITEM_FRAME_RADIUS 2
struct SubBruteMainView {
View* view;
@@ -17,7 +27,8 @@ struct SubBruteMainView {
void* context;
uint8_t index;
bool is_select_byte;
const char* key_field;
bool two_bytes;
uint64_t key_from_file;
uint8_t extra_repeats;
uint8_t window_position;
};
@@ -27,7 +38,8 @@ typedef struct {
uint8_t extra_repeats;
uint8_t window_position;
bool is_select_byte;
const char* key_field;
bool two_bytes;
uint64_t key_from_file;
} SubBruteMainViewModel;
void subbrute_main_view_set_callback(
@@ -41,84 +53,105 @@ void subbrute_main_view_set_callback(
instance->context = context;
}
FuriString* center_displayed_key(const char* key_cstr, uint8_t index) {
uint8_t str_index = (index * 3);
void subbrute_main_view_center_displayed_key(
Canvas* canvas,
uint64_t key,
uint8_t index,
bool two_bytes) {
uint8_t text_x = TEXT_X;
uint8_t item_x = TEXT_X - ITEMS_INTERVAL;
canvas_set_font(canvas, FontSecondary);
char display_menu[] = {
'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'};
for(int i = 0; i < 8; i++) {
char current_value[3] = {0};
uint8_t byte_value = (uint8_t)(key >> 8 * (7 - i)) & 0xFF;
snprintf(current_value, sizeof(current_value), "%02X", byte_value);
if(key_cstr != NULL) {
if(index > 1) {
display_menu[0] = key_cstr[str_index - 6];
display_menu[1] = key_cstr[str_index - 5];
// For two bytes we need to select prev location
if(!two_bytes && i == index) {
canvas_set_color(canvas, ColorBlack);
canvas_draw_rbox(
canvas, item_x - 1, ITEM_Y, ITEM_WIDTH + 1, ITEM_HEIGHT, ITEM_FRAME_RADIUS);
canvas_set_color(canvas, ColorWhite);
canvas_draw_str(canvas, text_x, TEXT_Y, current_value);
} else if(two_bytes && (i == index || i == index - 1)) {
if(i == index) {
canvas_set_color(canvas, ColorBlack);
canvas_draw_rbox(
canvas,
item_x - ITEMS_INTERVAL - ITEM_WIDTH - 1,
ITEM_Y,
ITEM_WIDTH * 2 + ITEMS_INTERVAL * 2 + 1,
ITEM_HEIGHT,
ITEM_FRAME_RADIUS);
canvas_set_color(canvas, ColorWhite);
canvas_draw_str(canvas, text_x, TEXT_Y, current_value);
// Redraw prev element with white
memset(current_value, 0, sizeof(current_value));
byte_value = (uint8_t)(key >> 8 * (7 - i + 1)) & 0xFF;
snprintf(current_value, sizeof(current_value), "%02X", byte_value);
canvas_draw_str(
canvas, text_x - (TEXT_WIDTH + TEXT_INTERVAL), TEXT_Y, current_value);
} else {
canvas_set_color(canvas, ColorWhite);
canvas_draw_str(canvas, text_x, TEXT_Y, current_value);
}
} else {
display_menu[0] = ' ';
display_menu[1] = ' ';
}
if(index > 0) {
display_menu[3] = key_cstr[str_index - 3];
display_menu[4] = key_cstr[str_index - 2];
} else {
display_menu[3] = ' ';
display_menu[4] = ' ';
}
display_menu[7] = key_cstr[str_index];
display_menu[8] = key_cstr[str_index + 1];
if((str_index + 4) <= (uint8_t)strlen(key_cstr)) {
display_menu[11] = key_cstr[str_index + 3];
display_menu[12] = key_cstr[str_index + 4];
} else {
display_menu[11] = ' ';
display_menu[12] = ' ';
}
if((str_index + 8) <= (uint8_t)strlen(key_cstr)) {
display_menu[14] = key_cstr[str_index + 6];
display_menu[15] = key_cstr[str_index + 7];
} else {
display_menu[14] = ' ';
display_menu[15] = ' ';
canvas_set_color(canvas, ColorBlack);
canvas_draw_str(canvas, text_x, TEXT_Y, current_value);
}
text_x = text_x + TEXT_WIDTH + TEXT_INTERVAL;
item_x = item_x + ITEM_WIDTH + ITEMS_INTERVAL;
}
return furi_string_alloc_set(display_menu);
// Return normal color
canvas_set_color(canvas, ColorBlack);
}
void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) {
// Title
canvas_set_font(canvas, FontPrimary);
canvas_draw_box(canvas, 0, 0, canvas_width(canvas), STATUS_BAR_Y_SHIFT);
canvas_invert_color(canvas);
canvas_draw_str_aligned(canvas, 64, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer 3.2");
canvas_invert_color(canvas);
uint16_t screen_width = canvas_width(canvas);
uint16_t screen_height = canvas_height(canvas);
if(model->is_select_byte) {
#ifdef FURI_DEBUG
//FURI_LOG_D(TAG, "key_field: %s", model->key_field);
//FURI_LOG_D(TAG, "key_from_file: %s", model->key_from_file);
#endif
char msg_index[18];
snprintf(msg_index, sizeof(msg_index), "Field index : %d", model->index);
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index);
FuriString* menu_items;
menu_items = center_displayed_key(model->key_field, model->index);
//char msg_index[18];
//snprintf(msg_index, sizeof(msg_index), "Field index: %d", model->index);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 64, 40, AlignCenter, AlignTop, furi_string_get_cstr(menu_items));
canvas, 64, 17, AlignCenter, AlignTop, "Please select values to calc:");
subbrute_main_view_center_displayed_key(
canvas, model->key_from_file, model->index, model->two_bytes);
//const char* line = furi_string_get_cstr(menu_items);
//canvas_set_font(canvas, FontSecondary);
//canvas_draw_str_aligned(
// canvas, 64, 37, AlignCenter, AlignTop, furi_string_get_cstr(menu_items));
elements_button_center(canvas, "Select");
elements_button_left(canvas, "<");
elements_button_right(canvas, ">");
furi_string_reset(menu_items);
furi_string_free(menu_items);
if(model->index > 0) {
elements_button_left(canvas, " ");
}
if(model->index < 7) {
elements_button_right(canvas, " ");
}
// Switch to another mode
if(model->two_bytes) {
elements_button_top_left(canvas, "One byte");
} else {
elements_button_top_left(canvas, "Two bytes");
}
} else {
// Title
canvas_set_font(canvas, FontPrimary);
canvas_draw_box(canvas, 0, 0, canvas_width(canvas), STATUS_BAR_Y_SHIFT);
canvas_invert_color(canvas);
canvas_draw_str_aligned(canvas, 64, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer 3.3");
canvas_invert_color(canvas);
// Menu
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
@@ -257,18 +290,34 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
}
}
}
} else {
if(event->key == InputKeyLeft && is_short) {
if(instance->index > 0) {
} else if(is_short) {
if(event->key == InputKeyLeft) {
if((instance->index > 0 && !instance->two_bytes) ||
(instance->two_bytes && instance->index > 1)) {
instance->index--;
}
updated = true;
} else if(event->key == InputKeyRight && is_short) {
consumed = true;
} else if(event->key == InputKeyRight) {
if(instance->index < 7) {
instance->index++;
}
updated = true;
} else if(event->key == InputKeyOk && is_short) {
consumed = true;
} else if(event->key == InputKeyUp) {
instance->two_bytes = !instance->two_bytes;
// Because index is changing
if(instance->two_bytes && instance->index < 7) {
instance->index++;
}
// instance->callback(
// instance->two_bytes ? SubBruteCustomEventTypeChangeStepUp :
// SubBruteCustomEventTypeChangeStepDown,
// instance->context);
updated = true;
consumed = true;
} else if(event->key == InputKeyOk) {
instance->callback(SubBruteCustomEventTypeIndexSelected, instance->context);
consumed = true;
updated = true;
@@ -282,8 +331,9 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
{
model->index = instance->index;
model->window_position = instance->window_position;
model->key_field = instance->key_field;
model->key_from_file = instance->key_from_file;
model->is_select_byte = instance->is_select_byte;
model->two_bytes = instance->two_bytes;
model->extra_repeats = instance->extra_repeats;
},
true);
@@ -318,24 +368,25 @@ SubBruteMainView* subbrute_main_view_alloc() {
view_set_enter_callback(instance->view, subbrute_main_view_enter);
view_set_exit_callback(instance->view, subbrute_main_view_exit);
instance->index = 0;
instance->window_position = 0;
instance->key_from_file = 0;
instance->is_select_byte = false;
instance->two_bytes = false;
instance->extra_repeats = 0;
with_view_model(
instance->view,
SubBruteMainViewModel * model,
{
model->index = 0;
model->window_position = 0;
model->key_field = NULL;
model->is_select_byte = false;
model->extra_repeats = 0;
model->index = instance->index;
model->window_position = instance->window_position;
model->key_from_file = instance->key_from_file;
model->is_select_byte = instance->is_select_byte;
model->two_bytes = instance->two_bytes;
model->extra_repeats = instance->extra_repeats;
},
true);
instance->index = 0;
instance->window_position = 0;
instance->key_field = NULL;
instance->is_select_byte = false;
instance->extra_repeats = 0;
return instance;
}
@@ -355,14 +406,16 @@ void subbrute_main_view_set_index(
SubBruteMainView* instance,
uint8_t idx,
bool is_select_byte,
const char* key_field) {
bool two_bytes,
uint64_t key_from_file) {
furi_assert(instance);
furi_assert(idx < SubBruteAttackTotalCount);
#ifdef FURI_DEBUG
FURI_LOG_I(TAG, "Set index: %d, IS_SELECT_BYTE: %d", idx, is_select_byte);
FURI_LOG_I(TAG, "Set index: %d, is_select_byte: %d", idx, is_select_byte);
#endif
instance->is_select_byte = is_select_byte;
instance->key_field = key_field;
instance->two_bytes = two_bytes;
instance->key_from_file = key_from_file;
instance->index = idx;
instance->window_position = idx;
@@ -386,8 +439,9 @@ void subbrute_main_view_set_index(
{
model->index = instance->index;
model->window_position = instance->window_position;
model->key_field = instance->key_field;
model->key_from_file = instance->key_from_file;
model->is_select_byte = instance->is_select_byte;
model->two_bytes = instance->two_bytes;
model->extra_repeats = instance->extra_repeats;
},
true);
@@ -401,4 +455,9 @@ SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance) {
uint8_t subbrute_main_view_get_extra_repeats(SubBruteMainView* instance) {
furi_assert(instance);
return instance->extra_repeats;
}
bool subbrute_main_view_get_two_bytes(SubBruteMainView* instance) {
furi_assert(instance);
return instance->two_bytes;
}

View File

@@ -21,9 +21,11 @@ void subbrute_main_view_set_index(
SubBruteMainView* instance,
uint8_t idx,
bool is_select_byte,
const char* key_field);
bool two_bytes,
uint64_t file_key);
SubBruteAttacks subbrute_main_view_get_index(SubBruteMainView* instance);
uint8_t subbrute_main_view_get_extra_repeats(SubBruteMainView* instance);
bool subbrute_main_view_get_two_bytes(SubBruteMainView* instance);
void subbrute_attack_view_enter(void* context);
void subbrute_attack_view_exit(void* context);
bool subbrute_attack_view_input(InputEvent* event, void* context);