mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-15 00:48:35 -07:00
Returned to Worker model
This commit is contained in:
362
applications/plugins/subbrute/helpers/subbrute_worker.c
Normal file
362
applications/plugins/subbrute/helpers/subbrute_worker.c
Normal file
@@ -0,0 +1,362 @@
|
||||
#include "subbrute_worker_private.h"
|
||||
#include <string.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <flipper_format.h>
|
||||
#include <flipper_format_i.h>
|
||||
|
||||
#define TAG "SubBruteWorker"
|
||||
#define SUBBRUTE_TX_TIMEOUT 5
|
||||
#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
|
||||
|
||||
SubBruteWorker* subbrute_worker_alloc() {
|
||||
SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
|
||||
|
||||
instance->state = SubBruteWorkerStateIDLE;
|
||||
instance->key_index = 0;
|
||||
instance->worker_running = false;
|
||||
instance->initiated = false;
|
||||
instance->last_time_tx_data = 0;
|
||||
instance->load_index = 0;
|
||||
|
||||
instance->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
|
||||
furi_thread_set_stack_size(instance->thread, 2048);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
furi_thread_set_callback(instance->thread, subbrute_worker_thread);
|
||||
|
||||
instance->context = NULL;
|
||||
instance->callback = NULL;
|
||||
|
||||
instance->decoder_result = NULL;
|
||||
instance->transmitter = NULL;
|
||||
instance->environment = subghz_environment_alloc();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subbrute_worker_free(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// I don't know how to free this
|
||||
instance->decoder_result = NULL;
|
||||
|
||||
if(instance->transmitter != NULL) {
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
furi_thread_free(instance->thread);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
uint64_t subbrute_worker_get_step(SubBruteWorker* instance) {
|
||||
return instance->key_index;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
instance->key_index = step;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subbrute_worker_init_default_attack(
|
||||
SubBruteWorker* instance,
|
||||
SubBruteAttacks attack_type,
|
||||
uint64_t step,
|
||||
const SubBruteProtocol* protocol) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Init Worker when it's running");
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
|
||||
instance->attack = attack_type;
|
||||
instance->frequency = protocol->frequency;
|
||||
instance->preset = protocol->preset;
|
||||
instance->file = protocol->file;
|
||||
instance->key_index = step;
|
||||
instance->bits = protocol->bits;
|
||||
instance->te = protocol->te;
|
||||
instance->load_index = 0;
|
||||
instance->file_key = NULL;
|
||||
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subbrute_worker_init_file_attack(
|
||||
SubBruteWorker* instance,
|
||||
uint64_t step,
|
||||
uint8_t load_index,
|
||||
const char* file_key,
|
||||
SubBruteProtocol* protocol) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Init Worker when it's running");
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
|
||||
instance->attack = SubBruteAttackLoadFile;
|
||||
instance->frequency = protocol->frequency;
|
||||
instance->preset = protocol->preset;
|
||||
instance->file = protocol->file;
|
||||
instance->key_index = step;
|
||||
instance->bits = protocol->bits;
|
||||
instance->te = protocol->te;
|
||||
instance->load_index = load_index;
|
||||
instance->file_key = file_key;
|
||||
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subbrute_worker_start(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(!instance->initiated) {
|
||||
FURI_LOG_W(TAG, "Worker not init!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker is already running!");
|
||||
return false;
|
||||
}
|
||||
if(instance->state != SubBruteWorkerStateReady &&
|
||||
instance->state != SubBruteWorkerStateFinished) {
|
||||
FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->worker_running = true;
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subbrute_worker_stop(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->worker_running = false;
|
||||
|
||||
furi_thread_join(instance->thread);
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
}
|
||||
|
||||
bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(!instance->initiated) {
|
||||
FURI_LOG_W(TAG, "Worker not init!");
|
||||
return false;
|
||||
}
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker in running state!");
|
||||
return false;
|
||||
}
|
||||
if(instance->state != SubBruteWorkerStateReady &&
|
||||
instance->state != SubBruteWorkerStateFinished) {
|
||||
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ticks = furi_get_tick();
|
||||
if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->last_time_tx_data = ticks;
|
||||
instance->key_index = step;
|
||||
|
||||
bool result;
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
FuriString* payload = furi_string_alloc();
|
||||
stream_clean(stream);
|
||||
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
payload = subbrute_protocol_file_payload(
|
||||
step,
|
||||
instance->bits,
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->load_index,
|
||||
instance->file_key);
|
||||
} else {
|
||||
payload = subbrute_protocol_default_payload(
|
||||
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;
|
||||
}
|
||||
|
||||
bool subbrute_worker_is_running(SubBruteWorker* instance) {
|
||||
return instance->worker_running;
|
||||
}
|
||||
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(!instance->initiated) {
|
||||
FURI_LOG_W(TAG, "Worker not init!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return !instance->worker_running && instance->state != SubBruteWorkerStateIDLE &&
|
||||
instance->state != SubBruteWorkerStateTx &&
|
||||
((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
|
||||
}
|
||||
|
||||
void subbrute_worker_set_callback(
|
||||
SubBruteWorker* instance,
|
||||
SubBruteWorkerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format) {
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, subbrute_protocol_name(instance->attack));
|
||||
subghz_transmitter_deserialize(instance->transmitter, flipper_format);
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
|
||||
|
||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
void subbrute_worker_send_callback(SubBruteWorker* instance) {
|
||||
if(instance->callback != NULL) {
|
||||
instance->callback(instance->context, instance->state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entrypoint for worker
|
||||
*
|
||||
* @param context SubBruteWorker*
|
||||
* @return 0 if ok
|
||||
*/
|
||||
int32_t subbrute_worker_thread(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteWorker* instance = (SubBruteWorker*)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
|
||||
FURI_LOG_I(TAG, "Worker start");
|
||||
#endif
|
||||
|
||||
SubBruteWorkerState local_state = instance->state = SubBruteWorkerStateTx;
|
||||
subbrute_worker_send_callback(instance);
|
||||
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
while(instance->worker_running) {
|
||||
FuriString* payload = furi_string_alloc();
|
||||
stream_clean(stream);
|
||||
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
payload = subbrute_protocol_file_payload(
|
||||
instance->key_index,
|
||||
instance->bits,
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->load_index,
|
||||
instance->file_key);
|
||||
} else {
|
||||
payload = subbrute_protocol_default_payload(
|
||||
instance->key_index, instance->bits, instance->te, instance->repeat);
|
||||
}
|
||||
|
||||
size_t written = 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->key_index + 1 > instance->max_value) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker finished to end");
|
||||
#endif
|
||||
local_state = SubBruteWorkerStateFinished;
|
||||
furi_string_free(payload);
|
||||
break;
|
||||
}
|
||||
instance->key_index++;
|
||||
|
||||
furi_string_free(payload);
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
|
||||
flipper_format_free(flipper_format);
|
||||
|
||||
instance->worker_running = false; // Because we have error states
|
||||
instance->state = local_state == SubBruteWorkerStateTx ? SubBruteWorkerStateReady :
|
||||
local_state;
|
||||
subbrute_worker_send_callback(instance);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker stop");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
39
applications/plugins/subbrute/helpers/subbrute_worker.h
Normal file
39
applications/plugins/subbrute/helpers/subbrute_worker.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "../subbrute_protocols.h"
|
||||
|
||||
typedef enum {
|
||||
SubBruteWorkerStateIDLE,
|
||||
SubBruteWorkerStateReady,
|
||||
SubBruteWorkerStateTx,
|
||||
SubBruteWorkerStateFinished
|
||||
} SubBruteWorkerState;
|
||||
|
||||
typedef void (*SubBruteWorkerCallback)(void* context, SubBruteWorkerState state);
|
||||
|
||||
typedef struct SubBruteWorker SubBruteWorker;
|
||||
|
||||
SubBruteWorker* subbrute_worker_alloc();
|
||||
void subbrute_worker_free(SubBruteWorker* instance);
|
||||
uint64_t subbrute_worker_get_step(SubBruteWorker* instance);
|
||||
bool subbrute_worker_set_step(SubBruteWorker* instance, uint64_t step);
|
||||
bool subbrute_worker_is_running(SubBruteWorker* instance);
|
||||
bool subbrute_worker_init_default_attack(
|
||||
SubBruteWorker* instance,
|
||||
SubBruteAttacks attack_type,
|
||||
uint64_t step,
|
||||
const SubBruteProtocol* protocol);
|
||||
bool subbrute_worker_init_file_attack(
|
||||
SubBruteWorker* instance,
|
||||
uint64_t step,
|
||||
uint8_t load_index,
|
||||
const char* file_key,
|
||||
SubBruteProtocol* protocol);
|
||||
bool subbrute_worker_start(SubBruteWorker* instance);
|
||||
void subbrute_worker_stop(SubBruteWorker* instance);
|
||||
bool subbrute_worker_transmit_current_key(SubBruteWorker* instance, uint64_t step);
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance);
|
||||
void subbrute_worker_set_callback(
|
||||
SubBruteWorker* instance,
|
||||
SubBruteWorkerCallback callback,
|
||||
void* context);
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "subbrute_worker.h"
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/environment.h>
|
||||
|
||||
struct SubBruteWorker {
|
||||
SubBruteWorkerState state;
|
||||
volatile bool worker_running;
|
||||
volatile bool initiated;
|
||||
|
||||
// Current step
|
||||
uint64_t key_index;
|
||||
|
||||
// SubGhz
|
||||
FuriThread* thread;
|
||||
SubGhzProtocolDecoderBase* decoder_result;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzTransmitter* transmitter;
|
||||
|
||||
// Initiated values
|
||||
SubBruteAttacks attack; // Attack state
|
||||
uint32_t frequency;
|
||||
FuriHalSubGhzPreset preset;
|
||||
SubBruteFileProtocol file;
|
||||
uint8_t bits;
|
||||
uint8_t te;
|
||||
uint8_t repeat;
|
||||
uint8_t load_index; // Index of group to bruteforce in loaded file
|
||||
const char* file_key;
|
||||
uint64_t max_value; // Max step
|
||||
|
||||
// Manual transmit
|
||||
uint32_t last_time_tx_data;
|
||||
|
||||
// Callback for changed states
|
||||
SubBruteWorkerCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
int32_t subbrute_worker_thread(void* context);
|
||||
void subbrute_worker_subghz_transmit(SubBruteWorker* instance, FlipperFormat* flipper_format);
|
||||
void subbrute_worker_send_callback(SubBruteWorker* instance);
|
||||
@@ -39,6 +39,14 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
||||
if(load_result == SubBruteFileResultOk) {
|
||||
load_result = subbrute_device_attack_set(instance->device, SubBruteAttackLoadFile);
|
||||
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->file_protocol_info)) {
|
||||
furi_crash("Invalid attack set!");
|
||||
}
|
||||
// Ready to run!
|
||||
FURI_LOG_I(TAG, "Ready to run");
|
||||
res = true;
|
||||
@@ -52,7 +60,8 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
||||
|
||||
FuriString* dialog_msg;
|
||||
dialog_msg = furi_string_alloc();
|
||||
furi_string_cat_printf(dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||
furi_string_cat_printf(
|
||||
dialog_msg, "Cannot parse\nfile: %s", subbrute_device_error_get_desc(load_result));
|
||||
dialog_message_show_storage_error(instance->dialogs, furi_string_get_cstr(dialog_msg));
|
||||
furi_string_free(dialog_msg);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
|
||||
@@ -20,7 +20,7 @@ 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, subbrute_device_get_file_key(instance->device));
|
||||
subbrute_main_view_set_index(view, 7, true, instance->device->file_key);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
}
|
||||
@@ -38,8 +38,15 @@ bool subbrute_scene_load_select_on_event(void* context, SceneManagerEvent event)
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubBruteCustomEventTypeIndexSelected) {
|
||||
subbrute_device_set_load_index(
|
||||
instance->device, subbrute_main_view_get_index(instance->view_main));
|
||||
instance->device->load_index = subbrute_main_view_get_index(instance->view_main);
|
||||
if(!subbrute_worker_init_file_attack(
|
||||
instance->worker,
|
||||
instance->device->key_index,
|
||||
instance->device->load_index,
|
||||
instance->device->file_key,
|
||||
instance->device->file_protocol_info)) {
|
||||
furi_crash("Invalid attack set!");
|
||||
}
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void*
|
||||
}
|
||||
|
||||
static void
|
||||
subbrute_scene_run_attack_device_state_changed(void* context, SubBruteDeviceState state) {
|
||||
subbrute_scene_run_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
|
||||
if(state == SubBruteDeviceStateIDLE) {
|
||||
if(state == SubBruteWorkerStateIDLE) {
|
||||
// Can't be IDLE on this step!
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||
} else if(state == SubBruteDeviceStateFinished) {
|
||||
} else if(state == SubBruteWorkerStateFinished) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
}
|
||||
@@ -28,7 +28,7 @@ void subbrute_scene_run_attack_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
|
||||
subbrute_worker_stop(instance->device);
|
||||
subbrute_worker_stop(instance->worker);
|
||||
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
@@ -42,11 +42,11 @@ void subbrute_scene_run_attack_on_enter(void* context) {
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
|
||||
subbrute_device_set_callback(
|
||||
instance->device, subbrute_scene_run_attack_device_state_changed, instance);
|
||||
subbrute_worker_set_callback(
|
||||
instance->worker, subbrute_scene_run_attack_device_state_changed, instance);
|
||||
|
||||
if(!subbrute_device_is_worker_running(instance->device)) {
|
||||
subbrute_worker_start(instance->device);
|
||||
if(!subbrute_worker_is_running(instance->worker)) {
|
||||
subbrute_worker_start(instance->worker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
subbrute_attack_view_set_current_step(view, subbrute_get_step(instance));
|
||||
subbrute_attack_view_set_current_step(view, subbrute_worker_get_step(instance->worker));
|
||||
|
||||
if(event.event == SubBruteCustomEventTypeTransmitFinished) {
|
||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||
@@ -77,7 +77,7 @@ bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event)
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
subbrute_attack_view_set_current_step(view, subbrute_get_step(instance));
|
||||
subbrute_attack_view_set_current_step(view, subbrute_worker_get_step(instance->worker));
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void
|
||||
}
|
||||
|
||||
static void
|
||||
subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteDeviceState state) {
|
||||
subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
|
||||
if(state == SubBruteDeviceStateIDLE) {
|
||||
if(state == SubBruteWorkerStateIDLE) {
|
||||
// Can't be IDLE on this step!
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||
}
|
||||
@@ -28,16 +28,24 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Enter Attack: %d", subbrute_device_get_attack(instance->device));
|
||||
FURI_LOG_D(TAG, "Enter Attack: %d", instance->device->attack);
|
||||
#endif
|
||||
|
||||
subbrute_device_set_callback(
|
||||
instance->device, subbrute_scene_setup_attack_device_state_changed, context);
|
||||
subbrute_worker_set_callback(
|
||||
instance->worker, subbrute_scene_setup_attack_device_state_changed, context);
|
||||
|
||||
if(subbrute_device_is_worker_running(instance->device)) {
|
||||
subbrute_worker_stop(instance->device);
|
||||
if(subbrute_worker_is_running(instance->worker)) {
|
||||
instance->device->key_index = subbrute_worker_get_step(instance->worker);
|
||||
subbrute_worker_stop(instance->worker);
|
||||
}
|
||||
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
false);
|
||||
|
||||
instance->current_view = SubBruteViewAttack;
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_setup_attack_callback, instance);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
@@ -49,7 +57,7 @@ void subbrute_scene_setup_attack_on_exit(void* context) {
|
||||
FURI_LOG_D(TAG, "subbrute_scene_setup_attack_on_exit");
|
||||
#endif
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
subbrute_worker_stop(instance->device);
|
||||
subbrute_worker_stop(instance->worker);
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
@@ -65,53 +73,60 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
subbrute_device_get_attack(instance->device),
|
||||
subbrute_device_get_max_value(instance->device),
|
||||
subbrute_device_get_step(instance->device),
|
||||
instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
|
||||
} else if(event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
subbrute_device_reset_step(instance->device);
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
subbrute_device_get_attack(instance->device),
|
||||
subbrute_device_get_max_value(instance->device),
|
||||
subbrute_device_get_step(instance->device),
|
||||
instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
||||
} else if(event.event == SubBruteCustomEventTypeError) {
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
} else if(event.event == SubBruteCustomEventTypeTransmitCustom) {
|
||||
// We can transmit only in not working states
|
||||
if(subbrute_device_can_manual_transmit(instance->device)) {
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker)) {
|
||||
// MANUAL Transmit!
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_green_100);
|
||||
subbrute_device_transmit_current_key(instance->device);
|
||||
subbrute_worker_transmit_current_key(
|
||||
instance->worker, instance->device->key_index);
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
|
||||
// +1
|
||||
uint64_t step = subbrute_device_add_step(instance->device, 1);
|
||||
subbrute_worker_set_step(instance->worker, step);
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) {
|
||||
// +50
|
||||
uint64_t step = subbrute_device_add_step(instance->device, 50);
|
||||
subbrute_worker_set_step(instance->worker, step);
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDown) {
|
||||
// -1
|
||||
uint64_t step = subbrute_device_add_step(instance->device, -1);
|
||||
subbrute_worker_set_step(instance->worker, step);
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) {
|
||||
// -50
|
||||
uint64_t step = subbrute_device_add_step(instance->device, -50);
|
||||
subbrute_worker_set_step(instance->worker, step);
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
subbrute_attack_view_set_current_step(view, subbrute_device_get_step(instance->device));
|
||||
if(subbrute_worker_is_running(instance->worker)) {
|
||||
instance->device->key_index = subbrute_worker_get_step(instance->worker);
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ 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, subbrute_device_get_attack(instance->device), false, NULL);
|
||||
subbrute_main_view_set_index(view, instance->device->attack, false, NULL);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
}
|
||||
@@ -46,7 +46,14 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == SubBruteCustomEventTypeMenuSelected) {
|
||||
SubBruteAttacks attack = subbrute_main_view_get_index(instance->view_main);
|
||||
|
||||
subbrute_device_attack_set(instance->device, attack);
|
||||
if(subbrute_device_attack_set(instance->device, attack) != SubBruteFileResultOk ||
|
||||
!subbrute_worker_init_default_attack(
|
||||
instance->worker,
|
||||
attack,
|
||||
instance->device->key_index,
|
||||
instance->device->protocol_info)) {
|
||||
furi_crash("Invalid attack set!");
|
||||
}
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
|
||||
consumed = true;
|
||||
|
||||
@@ -51,6 +51,9 @@ SubBruteState* subbrute_alloc() {
|
||||
// Devices
|
||||
instance->device = subbrute_device_alloc();
|
||||
|
||||
// SubBruteWorker
|
||||
instance->worker = subbrute_worker_alloc();
|
||||
|
||||
// TextInput
|
||||
instance->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@@ -96,8 +99,11 @@ SubBruteState* subbrute_alloc() {
|
||||
void subbrute_free(SubBruteState* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// SubBruteWorker
|
||||
subbrute_worker_stop(instance->worker);
|
||||
subbrute_worker_free(instance->worker);
|
||||
|
||||
// SubBruteDevice
|
||||
subbrute_worker_stop(instance->device);
|
||||
subbrute_device_free(instance->device);
|
||||
|
||||
// Notifications
|
||||
@@ -163,13 +169,6 @@ void subbrute_popup_closed_callback(void* context) {
|
||||
instance->view_dispatcher, SubBruteCustomEventTypePopupClosed);
|
||||
}
|
||||
|
||||
uint64_t subbrute_get_step(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = context;
|
||||
|
||||
return subbrute_device_get_step(instance->device);
|
||||
}
|
||||
|
||||
// ENTRYPOINT
|
||||
int32_t subbrute_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
@@ -8,40 +8,14 @@
|
||||
|
||||
#define TAG "SubBruteDevice"
|
||||
|
||||
#define SUBBRUTE_TX_TIMEOUT 5
|
||||
#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
|
||||
|
||||
/**
|
||||
* Values to not use less memory for packet parse operations
|
||||
*/
|
||||
static const char* subbrute_key_file_start =
|
||||
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d";
|
||||
static const char* subbrute_key_file_key = "%s\nKey: %s\nRepeat: %d\n";
|
||||
static const char* subbrute_key_file_key_with_tail = "%s\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\nRepeat: %d\nRepeat: %d\n";
|
||||
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||
|
||||
SubBruteDevice* subbrute_device_alloc() {
|
||||
SubBruteDevice* instance = malloc(sizeof(SubBruteDevice));
|
||||
|
||||
instance->state = SubBruteDeviceStateIDLE;
|
||||
instance->key_index = 0;
|
||||
instance->worker_running = false;
|
||||
instance->last_time_tx_data = 0;
|
||||
|
||||
instance->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(instance->thread, "SubBruteAttackWorker");
|
||||
furi_thread_set_stack_size(instance->thread, 2048);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
furi_thread_set_callback(instance->thread, subbrute_worker_thread);
|
||||
|
||||
instance->context = NULL;
|
||||
instance->callback = NULL;
|
||||
|
||||
instance->protocol_info = NULL;
|
||||
instance->file_protocol_info = NULL;
|
||||
instance->decoder_result = NULL;
|
||||
instance->transmitter = NULL;
|
||||
instance->receiver = NULL;
|
||||
instance->environment = subghz_environment_alloc();
|
||||
|
||||
@@ -61,137 +35,15 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
||||
instance->receiver = NULL;
|
||||
}
|
||||
|
||||
if(instance->transmitter != NULL) {
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
furi_thread_free(instance->thread);
|
||||
subbrute_device_free_protocol_info(instance);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entrypoint for worker
|
||||
*
|
||||
* @param context SubBruteWorker*
|
||||
* @return 0 if ok
|
||||
*/
|
||||
int32_t subbrute_worker_thread(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteDevice* instance = (SubBruteDevice*)context;
|
||||
|
||||
if(!instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
||||
return -1;
|
||||
}
|
||||
if(instance->state != SubBruteDeviceStateReady &&
|
||||
instance->state != SubBruteDeviceStateFinished) {
|
||||
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
||||
return -2;
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker start");
|
||||
#endif
|
||||
|
||||
SubBruteDeviceState local_state = instance->state = SubBruteDeviceStateTx;
|
||||
subbrute_device_send_callback(instance);
|
||||
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
|
||||
while(instance->worker_running) {
|
||||
if(!subbrute_device_create_packet_parsed(
|
||||
instance, flipper_format, instance->key_index, true)) {
|
||||
FURI_LOG_W(TAG, "Error creating packet! BREAK");
|
||||
instance->worker_running = false;
|
||||
local_state = SubBruteDeviceStateIDLE;
|
||||
break;
|
||||
}
|
||||
subbrute_device_subghz_transmit(instance, flipper_format);
|
||||
|
||||
if(instance->key_index + 1 > instance->max_value) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker finished to end");
|
||||
#endif
|
||||
local_state = SubBruteDeviceStateFinished;
|
||||
break;
|
||||
}
|
||||
instance->key_index++;
|
||||
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
|
||||
flipper_format_free(flipper_format);
|
||||
|
||||
instance->worker_running = false; // Because we have error states
|
||||
instance->state = local_state == SubBruteDeviceStateTx ? SubBruteDeviceStateReady :
|
||||
local_state;
|
||||
subbrute_device_send_callback(instance);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker stop");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool subbrute_worker_start(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker is already running!");
|
||||
return false;
|
||||
}
|
||||
if(instance->state != SubBruteDeviceStateReady &&
|
||||
instance->state != SubBruteDeviceStateFinished) {
|
||||
FURI_LOG_W(TAG, "Worker cannot start, invalid device state: %d", instance->state);
|
||||
return false;
|
||||
}
|
||||
if((instance->protocol_info == NULL && instance->attack != SubBruteAttackLoadFile) ||
|
||||
(instance->attack == SubBruteAttackLoadFile && instance->file_protocol_info == NULL)) {
|
||||
FURI_LOG_W(TAG, "Worker cannot start, protocol_info is NULL!");
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->worker_running = true;
|
||||
furi_thread_start(instance->thread);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subbrute_worker_stop(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->worker_running = false;
|
||||
|
||||
furi_thread_join(instance->thread);
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
}
|
||||
|
||||
SubBruteAttacks subbrute_device_get_attack(SubBruteDevice* instance) {
|
||||
return instance->attack;
|
||||
}
|
||||
bool subbrute_device_is_worker_running(SubBruteDevice* instance) {
|
||||
return instance->worker_running;
|
||||
}
|
||||
uint64_t subbrute_device_get_max_value(SubBruteDevice* instance) {
|
||||
return instance->max_value;
|
||||
}
|
||||
uint64_t subbrute_device_get_step(SubBruteDevice* instance) {
|
||||
return instance->key_index;
|
||||
}
|
||||
const char* subbrute_device_get_file_key(SubBruteDevice* instance) {
|
||||
return instance->file_key;
|
||||
}
|
||||
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
|
||||
if(!subbrute_device_can_manual_transmit(instance)) {
|
||||
return instance->key_index;
|
||||
}
|
||||
if(step > 0) {
|
||||
if((instance->key_index + step) - instance->max_value == 1) {
|
||||
instance->key_index = 0x00;
|
||||
@@ -220,122 +72,17 @@ uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step) {
|
||||
|
||||
return instance->key_index;
|
||||
}
|
||||
void subbrute_device_set_load_index(SubBruteDevice* instance, uint64_t load_index) {
|
||||
instance->load_index = load_index;
|
||||
}
|
||||
void subbrute_device_reset_step(SubBruteDevice* instance) {
|
||||
instance->key_index = 0x00;
|
||||
}
|
||||
void subbrute_device_subghz_transmit(SubBruteDevice* instance, FlipperFormat* flipper_format) {
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, subbrute_protocol_name(instance->attack));
|
||||
subghz_transmitter_deserialize(instance->transmitter, flipper_format);
|
||||
furi_hal_subghz_reset();
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
furi_hal_subghz_load_preset(instance->file_protocol_info->preset);
|
||||
furi_hal_subghz_set_frequency_and_path(instance->file_protocol_info->preset);
|
||||
} else {
|
||||
furi_hal_subghz_load_preset(instance->protocol_info->preset);
|
||||
furi_hal_subghz_set_frequency_and_path(instance->protocol_info->preset);
|
||||
}
|
||||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, instance->transmitter);
|
||||
|
||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
bool subbrute_device_transmit_current_key(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker in running state!");
|
||||
return false;
|
||||
}
|
||||
if(instance->state != SubBruteDeviceStateReady &&
|
||||
instance->state != SubBruteDeviceStateFinished) {
|
||||
FURI_LOG_W(TAG, "Invalid state for running worker! State: %d", instance->state);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ticks = furi_get_tick();
|
||||
if((ticks - instance->last_time_tx_data) < SUBBRUTE_MANUAL_TRANSMIT_INTERVAL) {
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Need to wait, current: %ld", ticks - instance->last_time_tx_data);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->last_time_tx_data = ticks;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Protocol: %d, Frequency: %ld",
|
||||
instance->file_protocol_info->file,
|
||||
instance->file_protocol_info->frequency);
|
||||
} else {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Protocol: %d, Frequency: %ld",
|
||||
instance->protocol_info->file,
|
||||
instance->protocol_info->frequency);
|
||||
}
|
||||
#endif
|
||||
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
|
||||
if(!subbrute_device_create_packet_parsed(instance, flipper_format, instance->key_index, true)) {
|
||||
FURI_LOG_W(TAG, "Error creating packet! EXIT");
|
||||
return false;
|
||||
}
|
||||
subbrute_device_subghz_transmit(instance, flipper_format);
|
||||
|
||||
flipper_format_free(flipper_format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subbrute_device_set_callback(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteDeviceWorkerCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->callback = callback;
|
||||
instance->context = context;
|
||||
}
|
||||
|
||||
bool subbrute_device_can_manual_transmit(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return !instance->worker_running && instance->state != SubBruteDeviceStateIDLE &&
|
||||
instance->state != SubBruteDeviceStateTx &&
|
||||
((furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_MANUAL_TRANSMIT_INTERVAL);
|
||||
}
|
||||
|
||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->state != SubBruteDeviceStateReady &&
|
||||
instance->state != SubBruteDeviceStateFinished) {
|
||||
FURI_LOG_W(TAG, "Worker is not set to running state!");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name);
|
||||
#endif
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
FuriString* file_content = furi_string_alloc();
|
||||
|
||||
bool result = false;
|
||||
do {
|
||||
@@ -343,7 +90,32 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subbrute_device_create_packet_parsed(instance, file, instance->key_index, false)) {
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
file_content = subbrute_protocol_file_generate_file(
|
||||
instance->file_protocol_info->frequency,
|
||||
instance->file_protocol_info->preset,
|
||||
instance->file_protocol_info->file,
|
||||
instance->key_index,
|
||||
instance->file_protocol_info->bits,
|
||||
instance->file_protocol_info->te,
|
||||
instance->file_protocol_info->repeat,
|
||||
instance->load_index,
|
||||
instance->file_key);
|
||||
} else {
|
||||
file_content = subbrute_protocol_default_generate_file(
|
||||
instance->protocol_info->frequency,
|
||||
instance->protocol_info->preset,
|
||||
instance->protocol_info->file,
|
||||
instance->key_index,
|
||||
instance->protocol_info->bits,
|
||||
instance->protocol_info->te,
|
||||
instance->protocol_info->repeat);
|
||||
}
|
||||
|
||||
Stream* stream = flipper_format_get_raw_stream(file);
|
||||
stream_clean(stream);
|
||||
size_t written = stream_write_string(stream, file_content);
|
||||
if(written <= 0) {
|
||||
FURI_LOG_E(TAG, "create_packet_parsed failed!");
|
||||
break;
|
||||
}
|
||||
@@ -352,140 +124,17 @@ bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_na
|
||||
} while(false);
|
||||
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "flipper_format_file_open_always failed!");
|
||||
FURI_LOG_E(TAG, "subbrute_device_save_file failed!");
|
||||
}
|
||||
|
||||
flipper_format_file_close(file);
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
furi_string_free(file_content);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool subbrute_device_create_packet_parsed(
|
||||
SubBruteDevice* instance,
|
||||
FlipperFormat* flipper_format,
|
||||
uint64_t step,
|
||||
bool small) {
|
||||
furi_assert(instance);
|
||||
|
||||
FuriString* candidate = furi_string_alloc();
|
||||
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
stream_clean(stream);
|
||||
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
if(step >= sizeof(instance->file_key)) {
|
||||
return false;
|
||||
}
|
||||
char subbrute_payload_byte[4];
|
||||
furi_string_set_str(candidate, instance->file_key);
|
||||
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)step);
|
||||
furi_string_replace_at(candidate, instance->load_index * 3, 3, subbrute_payload_byte);
|
||||
//snprintf(step_payload, sizeof(step_payload), "%02X", (uint8_t)instance->file_key[step]);
|
||||
|
||||
if(small) {
|
||||
if(instance->file_protocol_info->te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_small_with_tail,
|
||||
instance->file_protocol_info->bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->file_protocol_info->te,
|
||||
instance->file_protocol_info->repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_small_no_tail,
|
||||
instance->file_protocol_info->bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->file_protocol_info->repeat);
|
||||
}
|
||||
} else {
|
||||
if(instance->file_protocol_info->te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_key_with_tail,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->file_protocol_info->te,
|
||||
instance->file_protocol_info->repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_key,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->file_protocol_info->repeat);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//snprintf(step_payload, sizeof(step_payload), "%16X", step);
|
||||
//snprintf(step_payload, sizeof(step_payload), "%016llX", step);
|
||||
FuriString* buffer = furi_string_alloc();
|
||||
furi_string_printf(buffer, "%16llX", step);
|
||||
int j = 0;
|
||||
furi_string_set_str(candidate, " ");
|
||||
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);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
|
||||
if(small) {
|
||||
if(instance->protocol_info->te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_small_with_tail,
|
||||
instance->protocol_info->bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->protocol_info->te,
|
||||
instance->protocol_info->repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_small_no_tail,
|
||||
instance->protocol_info->bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->protocol_info->repeat);
|
||||
}
|
||||
} else {
|
||||
if(instance->protocol_info->te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_key_with_tail,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->protocol_info->te,
|
||||
instance->protocol_info->repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_key,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->protocol_info->repeat);
|
||||
}
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s", furi_string_get_cstr(candidate));
|
||||
#endif
|
||||
}
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
@@ -513,10 +162,18 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set");
|
||||
} else {
|
||||
protocol_check_result = SubBruteFileResultOk;
|
||||
|
||||
// Calc max value
|
||||
instance->max_value =
|
||||
subbrute_protocol_calc_max_value(instance->attack, instance->protocol_info->bits);
|
||||
}
|
||||
} else {
|
||||
// And here we need to set preset enum
|
||||
protocol_check_result = SubBruteFileResultOk;
|
||||
|
||||
// Calc max value
|
||||
instance->max_value =
|
||||
subbrute_protocol_calc_max_value(instance->attack, instance->file_protocol_info->bits);
|
||||
}
|
||||
|
||||
subghz_receiver_free(instance->receiver);
|
||||
@@ -526,56 +183,6 @@ SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBrute
|
||||
return SubBruteFileResultProtocolNotFound;
|
||||
}
|
||||
|
||||
// Calc max value
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
instance->max_value = 0x3F;
|
||||
|
||||
// Now we are ready to set file template for using in the future with snprintf
|
||||
// for sending attack payload ONLY for files!
|
||||
snprintf(
|
||||
instance->file_template,
|
||||
sizeof(instance->file_template),
|
||||
subbrute_key_file_start,
|
||||
instance->file_protocol_info->frequency,
|
||||
subbrute_protocol_preset(instance->file_protocol_info->preset),
|
||||
subbrute_protocol_file(instance->file_protocol_info->file),
|
||||
instance->file_protocol_info->bits);
|
||||
} else {
|
||||
FuriString* max_value_s;
|
||||
max_value_s = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < instance->protocol_info->bits; i++) {
|
||||
furi_string_cat_printf(max_value_s, "1");
|
||||
}
|
||||
instance->max_value = (uint64_t)strtol(furi_string_get_cstr(max_value_s), NULL, 2);
|
||||
furi_string_free(max_value_s);
|
||||
|
||||
// Now we are ready to set file template for using in the future with snprintf
|
||||
// for sending attack payload
|
||||
snprintf(
|
||||
instance->file_template,
|
||||
sizeof(instance->file_template),
|
||||
subbrute_key_file_start,
|
||||
instance->protocol_info->frequency,
|
||||
subbrute_protocol_preset(instance->protocol_info->preset),
|
||||
subbrute_protocol_file(instance->protocol_info->file),
|
||||
instance->protocol_info->bits);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"tail: %d, file_template: %s",
|
||||
instance->protocol_info->te,
|
||||
instance->file_template);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Init payload
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
if(subbrute_device_create_packet_parsed(instance, flipper_format, instance->key_index, false)) {
|
||||
instance->state = SubBruteDeviceStateReady;
|
||||
subbrute_device_send_callback(instance);
|
||||
}
|
||||
flipper_format_free(flipper_format);
|
||||
|
||||
return SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
@@ -751,7 +358,6 @@ void subbrute_device_attack_set_default_values(
|
||||
instance->attack = default_attack;
|
||||
instance->key_index = 0x00;
|
||||
instance->load_index = 0x00;
|
||||
memset(instance->file_template, 0, sizeof(instance->file_template));
|
||||
memset(instance->current_key, 0, sizeof(instance->current_key));
|
||||
|
||||
if(default_attack != SubBruteAttackLoadFile) {
|
||||
@@ -761,12 +367,6 @@ void subbrute_device_attack_set_default_values(
|
||||
}
|
||||
}
|
||||
|
||||
void subbrute_device_send_callback(SubBruteDevice* instance) {
|
||||
if(instance->callback != NULL) {
|
||||
instance->callback(instance->context, instance->state);
|
||||
}
|
||||
}
|
||||
|
||||
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||
const char* result;
|
||||
switch(error_id) {
|
||||
|
||||
@@ -31,19 +31,9 @@ typedef enum {
|
||||
SubBruteFileResultMissingOrIncorrectTe,
|
||||
} SubBruteFileResult;
|
||||
|
||||
typedef enum {
|
||||
SubBruteDeviceStateIDLE,
|
||||
SubBruteDeviceStateReady,
|
||||
SubBruteDeviceStateTx,
|
||||
SubBruteDeviceStateFinished
|
||||
} SubBruteDeviceState;
|
||||
|
||||
typedef void (*SubBruteDeviceWorkerCallback)(void* context, SubBruteDeviceState state);
|
||||
typedef struct {
|
||||
SubBruteDeviceState state;
|
||||
const SubBruteProtocol* protocol_info;
|
||||
SubBruteProtocol* file_protocol_info;
|
||||
volatile bool worker_running;
|
||||
|
||||
// Current step
|
||||
uint64_t key_index;
|
||||
@@ -51,28 +41,17 @@ typedef struct {
|
||||
uint8_t load_index;
|
||||
|
||||
// SubGhz
|
||||
FuriThread* thread;
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzProtocolDecoderBase* decoder_result;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzTransmitter* transmitter;
|
||||
|
||||
// Attack state
|
||||
SubBruteAttacks attack;
|
||||
char file_template[SUBBRUTE_TEXT_STORE_SIZE];
|
||||
|
||||
uint64_t max_value;
|
||||
|
||||
// Loaded info for attack type
|
||||
char current_key[SUBBRUTE_PAYLOAD_SIZE];
|
||||
char file_key[SUBBRUTE_MAX_LEN_NAME];
|
||||
|
||||
// Manual transmit
|
||||
uint32_t last_time_tx_data;
|
||||
|
||||
// Callback for changed states
|
||||
SubBruteDeviceWorkerCallback callback;
|
||||
void* context;
|
||||
} SubBruteDevice;
|
||||
|
||||
SubBruteDevice* subbrute_device_alloc();
|
||||
@@ -83,33 +62,9 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id);
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type);
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
|
||||
|
||||
bool subbrute_device_is_worker_running(SubBruteDevice* instance);
|
||||
SubBruteAttacks subbrute_device_get_attack(SubBruteDevice* instance);
|
||||
uint64_t subbrute_device_get_max_value(SubBruteDevice* instance);
|
||||
uint64_t subbrute_device_get_step(SubBruteDevice* instance);
|
||||
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step);
|
||||
void subbrute_device_set_load_index(SubBruteDevice* instance, uint64_t load_index);
|
||||
void subbrute_device_reset_step(SubBruteDevice* instance);
|
||||
const char* subbrute_device_get_file_key(SubBruteDevice* instance);
|
||||
|
||||
bool subbrute_worker_start(SubBruteDevice* instance);
|
||||
void subbrute_worker_stop(SubBruteDevice* instance);
|
||||
bool subbrute_device_transmit_current_key(SubBruteDevice* instance);
|
||||
bool subbrute_device_can_manual_transmit(SubBruteDevice* instance);
|
||||
void subbrute_device_set_callback(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteDeviceWorkerCallback callback,
|
||||
void* context);
|
||||
|
||||
void subbrute_device_free_protocol_info(SubBruteDevice* instance);
|
||||
int32_t subbrute_worker_thread(void* context);
|
||||
void subbrute_device_attack_set_default_values(
|
||||
SubBruteDevice* context,
|
||||
SubBruteAttacks default_attack);
|
||||
bool subbrute_device_create_packet_parsed(
|
||||
SubBruteDevice* instance,
|
||||
FlipperFormat* flipper_format,
|
||||
uint64_t step,
|
||||
bool small);
|
||||
void subbrute_device_send_callback(SubBruteDevice* instance);
|
||||
void subbrute_device_subghz_transmit(SubBruteDevice* instance, FlipperFormat* flipper_format);
|
||||
SubBruteAttacks default_attack);
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "subbrute.h"
|
||||
#include "subbrute_device.h"
|
||||
#include "helpers/subbrute_worker.h"
|
||||
#include "views/subbrute_attack_view.h"
|
||||
#include "views/subbrute_main_view.h"
|
||||
|
||||
@@ -62,9 +63,10 @@ struct SubBruteState {
|
||||
|
||||
// SubBruteDevice
|
||||
SubBruteDevice* device;
|
||||
// SubBruteWorker
|
||||
SubBruteWorker* worker;
|
||||
};
|
||||
|
||||
void subbrute_show_loading_popup(void* context, bool show);
|
||||
void subbrute_text_input_callback(void* context);
|
||||
void subbrute_popup_closed_callback(void* context);
|
||||
uint64_t subbrute_get_step(void* context);
|
||||
void subbrute_popup_closed_callback(void* context);
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "subbrute_protocols.h"
|
||||
|
||||
#define TAG "SubBruteProtocols"
|
||||
|
||||
/**
|
||||
* CAME 12bit 303MHz
|
||||
*/
|
||||
@@ -201,6 +203,16 @@ static const char* subbrute_protocol_file_types[] = {
|
||||
[PrincetonFileProtocol] = "Princeton",
|
||||
[RAWFileProtocol] = "RAW"};
|
||||
|
||||
/**
|
||||
* Values to not use less memory for packet parse operations
|
||||
*/
|
||||
static const char* subbrute_key_file_start_no_tail =
|
||||
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\nKey: %s\nRepeat: %d\n";
|
||||
static const char* subbrute_key_file_start_with_tail =
|
||||
"Filetype: Flipper SubGhz Key File\nVersion: 1\nFrequency: %u\nPreset: %s\nProtocol: %s\nBit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\nRepeat: %d\nRepeat: %d\n";
|
||||
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\nRepeat: %d\n";
|
||||
|
||||
const char* subbrute_protocol_name(SubBruteAttacks index) {
|
||||
return subbrute_protocol_names[index];
|
||||
}
|
||||
@@ -235,4 +247,210 @@ SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) {
|
||||
}
|
||||
|
||||
return RAWFileProtocol;
|
||||
}
|
||||
|
||||
FuriString*
|
||||
subbrute_protocol_default_payload(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);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
FuriString* result;
|
||||
|
||||
if(te) {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_small_with_tail, bits, furi_string_get_cstr(candidate), te, repeat);
|
||||
} else {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||
#endif
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FuriString* subbrute_protocol_file_payload(
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat,
|
||||
uint8_t load_index,
|
||||
const char* file_key) {
|
||||
FuriString* candidate = furi_string_alloc();
|
||||
if(step >= sizeof(file_key)) {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
FuriString* result;
|
||||
|
||||
if(te) {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_small_with_tail, bits, furi_string_get_cstr(candidate), te, repeat);
|
||||
} else {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||
#endif
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FuriString* subbrute_protocol_default_generate_file(
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
SubBruteFileProtocol file,
|
||||
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);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
FuriString* result;
|
||||
|
||||
if(te) {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_file_start_with_tail,
|
||||
frequency,
|
||||
preset,
|
||||
file,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_file_start_no_tail,
|
||||
frequency,
|
||||
preset,
|
||||
file,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
repeat);
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||
#endif
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FuriString* subbrute_protocol_file_generate_file(
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
SubBruteFileProtocol file,
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat,
|
||||
uint8_t load_index,
|
||||
const char* file_key) {
|
||||
FuriString* candidate = furi_string_alloc();
|
||||
if(step >= sizeof(file_key)) {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
FuriString* result;
|
||||
|
||||
if(te) {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_file_start_with_tail,
|
||||
frequency,
|
||||
preset,
|
||||
file,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
result = furi_string_alloc_printf(
|
||||
subbrute_key_file_start_no_tail,
|
||||
frequency,
|
||||
preset,
|
||||
file,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
repeat);
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "result: %s", furi_string_get_cstr(result));
|
||||
#endif
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) {
|
||||
uint64_t max_value;
|
||||
if(attack_type == SubBruteAttackLoadFile) {
|
||||
max_value = 0x3F;
|
||||
} else {
|
||||
FuriString* max_value_s;
|
||||
max_value_s = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < bits; i++) {
|
||||
furi_string_cat_printf(max_value_s, "1");
|
||||
}
|
||||
max_value = (uint64_t)strtol(furi_string_get_cstr(max_value_s), NULL, 2);
|
||||
furi_string_free(max_value_s);
|
||||
}
|
||||
|
||||
return max_value;
|
||||
}
|
||||
@@ -54,4 +54,33 @@ const char* subbrute_protocol_preset(FuriHalSubGhzPreset preset);
|
||||
const char* subbrute_protocol_file(SubBruteFileProtocol protocol);
|
||||
FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name);
|
||||
SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name);
|
||||
const char* subbrute_protocol_name(SubBruteAttacks index);
|
||||
const char* subbrute_protocol_name(SubBruteAttacks index);
|
||||
|
||||
FuriString*
|
||||
subbrute_protocol_default_payload(uint64_t step, uint8_t bits, uint8_t te, uint8_t repeat);
|
||||
FuriString* subbrute_protocol_file_payload(
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat,
|
||||
uint8_t load_index,
|
||||
const char* file_key);
|
||||
FuriString* subbrute_protocol_default_generate_file(
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
SubBruteFileProtocol file,
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat);
|
||||
FuriString* subbrute_protocol_file_generate_file(
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
SubBruteFileProtocol file,
|
||||
uint64_t step,
|
||||
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);
|
||||
@@ -227,10 +227,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
with_view_model(
|
||||
instance->view, (SubBruteMainViewModel * model) {
|
||||
index = model->index;
|
||||
return false;
|
||||
});
|
||||
instance->view, SubBruteMainViewModel * model, { index = model->index; }, false);
|
||||
FURI_LOG_I(TAG, "Index: %d", index);
|
||||
#endif
|
||||
|
||||
@@ -265,10 +262,7 @@ bool subbrute_main_view_input(InputEvent* event, void* context) {
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
with_view_model(
|
||||
instance->view, (SubBruteMainViewModel * model) {
|
||||
index = model->index;
|
||||
return false;
|
||||
});
|
||||
instance->view, SubBruteMainViewModel * model, { index = model->index; }, false);
|
||||
FURI_LOG_I(TAG, "Index: %d", index);
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user