mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-11 19:33:30 -07:00
@@ -1,126 +1,185 @@
|
||||
#include "subbrute_worker.h"
|
||||
|
||||
#include <subghz/environment.h>
|
||||
#include <subghz/transmitter.h>
|
||||
#include "subbrute_worker_private.h"
|
||||
#include <string.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <flipper_format.h>
|
||||
#include <flipper_format_i.h>
|
||||
#include <lib/subghz/subghz_tx_rx_worker.h>
|
||||
|
||||
#define TAG "SubBruteWorker"
|
||||
|
||||
struct SubBruteWorker {
|
||||
SubGhzTxRxWorker* subghz_txrx;
|
||||
volatile bool worker_running;
|
||||
volatile bool worker_manual_mode;
|
||||
bool is_manual_init;
|
||||
bool is_continuous_worker;
|
||||
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzTransmitter* transmitter;
|
||||
FlipperFormat* flipper_format;
|
||||
|
||||
uint32_t last_time_tx_data;
|
||||
|
||||
// Preset and frequency needed
|
||||
FuriHalSubGhzPreset preset;
|
||||
uint32_t frequency;
|
||||
FuriString* protocol_name;
|
||||
|
||||
//SubBruteWorkerCallback callback;
|
||||
//void* context;
|
||||
};
|
||||
|
||||
/** Taken from subghz_tx_rx_worker.c */
|
||||
#define SUBBRUTE_TXRX_WORKER_BUF_SIZE 2048
|
||||
#define SUBBRUTE_TXRX_WORKER_MAX_TXRX_SIZE 60
|
||||
#define SUBBRUTE_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40
|
||||
#define SUBBRUTE_TX_TIMEOUT 5
|
||||
#define SUBBRUTE_SEND_DELAY 20
|
||||
#define SUBBRUTE_MANUAL_TRANSMIT_INTERVAL 400
|
||||
|
||||
SubBruteWorker* subbrute_worker_alloc() {
|
||||
SubBruteWorker* instance = malloc(sizeof(SubBruteWorker));
|
||||
|
||||
//instance->status = SubBruteWorkerStatusIDLE;
|
||||
instance->state = SubBruteWorkerStateIDLE;
|
||||
instance->step = 0;
|
||||
instance->worker_running = false;
|
||||
instance->worker_manual_mode = false;
|
||||
instance->initiated = false;
|
||||
instance->last_time_tx_data = 0;
|
||||
instance->load_index = 0;
|
||||
|
||||
//instance->environment = subghz_environment_alloc();
|
||||
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();
|
||||
|
||||
instance->flipper_format = flipper_format_string_alloc();
|
||||
instance->protocol_name = furi_string_alloc();
|
||||
|
||||
// SubGhzTxRxWorker
|
||||
instance->subghz_txrx = subghz_tx_rx_worker_alloc();
|
||||
instance->transmit_mode = false;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subbrute_worker_free(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(!instance->worker_running);
|
||||
|
||||
// I don't know how to free this
|
||||
instance->decoder_result = NULL;
|
||||
|
||||
if(instance->transmitter != NULL) {
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
/*if(instance->environment != NULL) {
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
}*/
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
flipper_format_free(instance->flipper_format);
|
||||
|
||||
furi_string_free(instance->protocol_name);
|
||||
|
||||
// SubGhzTxRxWorker
|
||||
subghz_tx_rx_worker_free(instance->subghz_txrx);
|
||||
furi_thread_free(instance->thread);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subbrute_worker_start(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name) {
|
||||
furi_assert(instance);
|
||||
uint64_t subbrute_worker_get_step(SubBruteWorker* instance) {
|
||||
return instance->step;
|
||||
}
|
||||
|
||||
if(instance->worker_manual_mode) {
|
||||
FURI_LOG_W(TAG, "Invalid mode for starting worker!");
|
||||
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->frequency = frequency;
|
||||
instance->preset = preset;
|
||||
instance->step = step;
|
||||
|
||||
furi_string_free(instance->protocol_name);
|
||||
instance->protocol_name = furi_string_alloc_printf("%s", protocol_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
bool subbrute_worker_init_default_attack(
|
||||
SubBruteWorker* instance,
|
||||
SubBruteAttacks attack_type,
|
||||
uint64_t step,
|
||||
const SubBruteProtocol* protocol) {
|
||||
furi_assert(instance);
|
||||
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
|
||||
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
furi_hal_subghz_flush_rx();
|
||||
|
||||
//if(furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
instance->frequency = frequency;
|
||||
res = true;
|
||||
//}
|
||||
instance->worker_running = res;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Frequency: %ld", frequency);
|
||||
#endif
|
||||
instance->preset = preset;
|
||||
if(res) {
|
||||
instance->worker_running = res =
|
||||
subghz_tx_rx_worker_start(instance->subghz_txrx, frequency);
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Init Worker when it's running");
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
return res;
|
||||
|
||||
instance->attack = attack_type;
|
||||
instance->frequency = protocol->frequency;
|
||||
instance->preset = protocol->preset;
|
||||
instance->file = protocol->file;
|
||||
instance->step = step;
|
||||
instance->bits = protocol->bits;
|
||||
instance->te = protocol->te;
|
||||
instance->repeat = protocol->repeat;
|
||||
instance->load_index = 0;
|
||||
instance->file_key = NULL;
|
||||
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||
|
||||
instance->initiated = true;
|
||||
instance->state = SubBruteWorkerStateReady;
|
||||
subbrute_worker_send_callback(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"subbrute_worker_init_default_attack: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
|
||||
subbrute_protocol_name(instance->attack),
|
||||
instance->bits,
|
||||
subbrute_protocol_preset(instance->preset),
|
||||
subbrute_protocol_file(instance->file),
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->max_value);
|
||||
#endif
|
||||
|
||||
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->step = step;
|
||||
instance->bits = protocol->bits;
|
||||
instance->te = protocol->te;
|
||||
instance->load_index = load_index;
|
||||
instance->repeat = protocol->repeat;
|
||||
instance->file_key = file_key;
|
||||
instance->max_value = subbrute_protocol_calc_max_value(instance->attack, instance->bits);
|
||||
|
||||
instance->initiated = true;
|
||||
instance->state = SubBruteWorkerStateReady;
|
||||
subbrute_worker_send_callback(instance);
|
||||
#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_protocol_name(instance->attack),
|
||||
instance->bits,
|
||||
subbrute_protocol_preset(instance->preset),
|
||||
subbrute_protocol_file(instance->file),
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->max_value);
|
||||
#endif
|
||||
|
||||
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) {
|
||||
@@ -128,204 +187,122 @@ void subbrute_worker_stop(SubBruteWorker* instance) {
|
||||
|
||||
instance->worker_running = false;
|
||||
|
||||
if(subghz_tx_rx_worker_is_running(instance->subghz_txrx)) {
|
||||
subghz_tx_rx_worker_stop(instance->subghz_txrx);
|
||||
}
|
||||
}
|
||||
|
||||
void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->is_continuous_worker = is_continuous_worker;
|
||||
}
|
||||
|
||||
bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->is_continuous_worker;
|
||||
}
|
||||
|
||||
bool subbrute_worker_is_running(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return instance->worker_running;
|
||||
}
|
||||
|
||||
bool subbrute_worker_can_transmit(SubBruteWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
return (furi_get_tick() - instance->last_time_tx_data) > SUBBRUTE_SEND_DELAY;
|
||||
}
|
||||
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(is_button_pressed) {
|
||||
// It's human pressed, trying to reset twice pressing
|
||||
return !instance->worker_manual_mode &&
|
||||
(furi_get_tick() - instance->last_time_tx_data) > 500;
|
||||
} else {
|
||||
return !instance->worker_manual_mode;
|
||||
}
|
||||
}
|
||||
|
||||
bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->worker_running);
|
||||
|
||||
if(!subbrute_worker_can_transmit(instance)) {
|
||||
FURI_LOG_E(TAG, "Too early to transmit");
|
||||
|
||||
return false;
|
||||
}
|
||||
instance->last_time_tx_data = furi_get_tick();
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
//FURI_LOG_D(TAG, "payload: %s", payload);
|
||||
#endif
|
||||
|
||||
while(!subghz_tx_rx_worker_write(instance->subghz_txrx, (uint8_t*)payload, strlen(payload))) {
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
|
||||
furi_hal_subghz_flush_tx();
|
||||
// Stream* stream = flipper_format_get_raw_stream(instance->flipper_format);
|
||||
// stream_clean(stream);
|
||||
// stream_write_cstring(stream, payload);
|
||||
// subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init MANUAL
|
||||
bool subbrute_worker_init_manual_transmit(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"subbrute_worker_init_manual_transmit. frequency: %ld, protocol: %s",
|
||||
frequency,
|
||||
protocol_name);
|
||||
#endif
|
||||
if(instance->worker_manual_mode || !subbrute_worker_can_manual_transmit(instance, false) ||
|
||||
instance->worker_running) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "cannot transmit");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(instance->worker_running) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_worker_stop");
|
||||
#endif
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
|
||||
// Not transmit at this period
|
||||
instance->worker_manual_mode = true;
|
||||
|
||||
if(instance->is_manual_init) {
|
||||
FURI_LOG_E(TAG, "Trying to setup without normally shutdown prev transmit session!");
|
||||
subbrute_worker_manual_transmit_stop(instance);
|
||||
}
|
||||
|
||||
instance->preset = preset;
|
||||
instance->frequency = frequency;
|
||||
|
||||
furi_string_free(instance->protocol_name);
|
||||
instance->protocol_name = furi_string_alloc_printf("%s", protocol_name);
|
||||
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
|
||||
furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
furi_hal_subghz_flush_rx();
|
||||
|
||||
/*if(!furi_hal_subghz_is_tx_allowed(frequency)) {
|
||||
FURI_LOG_E(TAG, "Frequency: %d invalid!", frequency);
|
||||
|
||||
instance->frequency = frequency;
|
||||
instance->worker_manual_mode = false;
|
||||
return false;
|
||||
}*/
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Frequency: %ld", frequency);
|
||||
#endif
|
||||
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, furi_string_get_cstr(instance->protocol_name));
|
||||
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
instance->frequency = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
furi_thread_join(instance->thread);
|
||||
|
||||
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
|
||||
furi_hal_subghz_sleep();
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
|
||||
instance->worker_manual_mode = false;
|
||||
instance->is_manual_init = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subbrute_worker_manual_transmit_stop(SubBruteWorker* instance) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_worker_manual_transmit_stop");
|
||||
#endif
|
||||
if(!instance->is_manual_init) {
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_sleep();
|
||||
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->step = step;
|
||||
|
||||
bool result;
|
||||
instance->protocol_name = subbrute_protocol_file(instance->file);
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
stream_clean(stream);
|
||||
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
subbrute_protocol_file_payload(
|
||||
stream,
|
||||
step,
|
||||
instance->bits,
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->load_index,
|
||||
instance->file_key);
|
||||
} else {
|
||||
subbrute_protocol_default_payload(
|
||||
stream, 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) {
|
||||
while(instance->transmit_mode) {
|
||||
furi_delay_ms(SUBBRUTE_TX_TIMEOUT);
|
||||
}
|
||||
instance->transmit_mode = true;
|
||||
if(instance->transmitter != NULL) {
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
}
|
||||
|
||||
instance->is_manual_init = false;
|
||||
}
|
||||
|
||||
bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->worker_manual_mode || !subbrute_worker_can_transmit(instance)) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "cannot transmit");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if(instance->worker_running) {
|
||||
FURI_LOG_W(TAG, "Worker was working for manual mode. Shutdown thread");
|
||||
subbrute_worker_stop(instance);
|
||||
}
|
||||
if(!instance->is_manual_init) {
|
||||
FURI_LOG_E(TAG, "Manually transmit doesn't set!");
|
||||
return false;
|
||||
}
|
||||
|
||||
instance->last_time_tx_data = furi_get_tick();
|
||||
instance->worker_manual_mode = true;
|
||||
|
||||
Stream* stream = flipper_format_get_raw_stream(instance->flipper_format);
|
||||
stream_clean(stream);
|
||||
stream_write_cstring(stream, payload);
|
||||
|
||||
instance->transmitter = subghz_transmitter_alloc_init(
|
||||
instance->environment, furi_string_get_cstr(instance->protocol_name));
|
||||
subghz_transmitter_deserialize(instance->transmitter, instance->flipper_format);
|
||||
instance->transmitter =
|
||||
subghz_transmitter_alloc_init(instance->environment, instance->protocol_name);
|
||||
subghz_transmitter_deserialize(instance->transmitter, flipper_format);
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_load_preset(instance->preset);
|
||||
instance->frequency = furi_hal_subghz_set_frequency_and_path(instance->frequency);
|
||||
|
||||
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()) {
|
||||
@@ -338,9 +315,100 @@ bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* paylo
|
||||
subghz_transmitter_free(instance->transmitter);
|
||||
instance->transmitter = NULL;
|
||||
|
||||
stream_clean(stream);
|
||||
instance->transmit_mode = false;
|
||||
}
|
||||
|
||||
instance->worker_manual_mode = false;
|
||||
void subbrute_worker_send_callback(SubBruteWorker* instance) {
|
||||
if(instance->callback != NULL) {
|
||||
instance->callback(instance->context, instance->state);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
|
||||
instance->protocol_name = subbrute_protocol_file(instance->file);
|
||||
|
||||
FlipperFormat* flipper_format = flipper_format_string_alloc();
|
||||
Stream* stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
while(instance->worker_running) {
|
||||
stream_clean(stream);
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
subbrute_protocol_file_payload(
|
||||
stream,
|
||||
instance->step,
|
||||
instance->bits,
|
||||
instance->te,
|
||||
instance->repeat,
|
||||
instance->load_index,
|
||||
instance->file_key);
|
||||
} else {
|
||||
subbrute_protocol_default_payload(
|
||||
stream, instance->step, instance->bits, instance->te, instance->repeat);
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
//FURI_LOG_I(TAG, "Payload: %s", furi_string_get_cstr(payload));
|
||||
//furi_delay_ms(SUBBRUTE_MANUAL_TRANSMIT_INTERVAL / 4);
|
||||
#endif
|
||||
|
||||
// size_t written = stream_write_stream_write_string(stream, payload);
|
||||
// if(written <= 0) {
|
||||
// FURI_LOG_W(TAG, "Error creating packet! BREAK");
|
||||
// instance->worker_running = false;
|
||||
// local_state = SubBruteWorkerStateIDLE;
|
||||
// furi_string_free(payload);
|
||||
// break;
|
||||
// }
|
||||
|
||||
subbrute_worker_subghz_transmit(instance, flipper_format);
|
||||
|
||||
if(instance->step + 1 > instance->max_value) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Worker finished to end");
|
||||
#endif
|
||||
local_state = SubBruteWorkerStateFinished;
|
||||
// furi_string_free(payload);
|
||||
break;
|
||||
}
|
||||
instance->step++;
|
||||
|
||||
// furi_string_free(payload);
|
||||
furi_delay_ms(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;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_subghz.h>
|
||||
|
||||
typedef struct SubBruteWorker SubBruteWorker;
|
||||
/**
|
||||
* Same like SubGhzTxRxWorkerStatus in subghz_tx_rx_worker.h
|
||||
* using just to not include that file
|
||||
#include "../subbrute_protocols.h"
|
||||
|
||||
typedef enum {
|
||||
SubBruteWorkerStatusIDLE,
|
||||
SubBruteWorkerStatusTx,
|
||||
// SubBruteWorkerStatusRx,
|
||||
} SubBruteWorkerStatus;
|
||||
SubBruteWorkerStateIDLE,
|
||||
SubBruteWorkerStateReady,
|
||||
SubBruteWorkerStateTx,
|
||||
SubBruteWorkerStateFinished
|
||||
} SubBruteWorkerState;
|
||||
|
||||
typedef void (*SubBruteWorkerCallback)(void* context, SubBruteWorkerState state);
|
||||
|
||||
typedef struct SubBruteWorker SubBruteWorker;
|
||||
|
||||
//typedef void (*SubBruteWorkerCallback)(SubBruteWorkerStatus event, void* context);
|
||||
*/
|
||||
SubBruteWorker* subbrute_worker_alloc();
|
||||
void subbrute_worker_free(SubBruteWorker* instance);
|
||||
bool subbrute_worker_start(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name);
|
||||
void subbrute_worker_stop(SubBruteWorker* instance);
|
||||
bool subbrute_worker_get_continuous_worker(SubBruteWorker* instance);
|
||||
void subbrute_worker_set_continuous_worker(SubBruteWorker* instance, bool is_continuous_worker);
|
||||
//bool subbrute_worker_write(SubBruteWorker* instance, uint8_t* data, size_t size);
|
||||
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_can_transmit(SubBruteWorker* instance);
|
||||
bool subbrute_worker_can_manual_transmit(SubBruteWorker* instance, bool is_button_pressed);
|
||||
bool subbrute_worker_transmit(SubBruteWorker* instance, const char* payload);
|
||||
bool subbrute_worker_init_manual_transmit(
|
||||
bool subbrute_worker_init_default_attack(
|
||||
SubBruteWorker* instance,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
const char* protocol_name);
|
||||
bool subbrute_worker_manual_transmit(SubBruteWorker* instance, const char* payload);
|
||||
void subbrute_worker_manual_transmit_stop(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,47 @@
|
||||
#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;
|
||||
volatile bool transmit_mode;
|
||||
|
||||
// Current step
|
||||
uint64_t step;
|
||||
|
||||
// SubGhz
|
||||
FuriThread* thread;
|
||||
SubGhzProtocolDecoderBase* decoder_result;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzTransmitter* transmitter;
|
||||
const char* protocol_name;
|
||||
|
||||
// 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);
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include <lib/subghz/protocols/registry.h>
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteSceneLoadFile"
|
||||
|
||||
@@ -35,12 +34,20 @@ void subbrute_scene_load_file_on_enter(void* context) {
|
||||
furi_string_get_cstr(app_folder));
|
||||
#endif
|
||||
if(res) {
|
||||
load_result = subbrute_device_load_from_file(instance->device, load_path);
|
||||
load_result =
|
||||
subbrute_device_load_from_file(instance->device, furi_string_get_cstr(load_path));
|
||||
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!
|
||||
instance->device->state = SubBruteDeviceStateReady;
|
||||
FURI_LOG_I(TAG, "Ready to run");
|
||||
res = true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "../views/subbrute_main_view.h"
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteSceneStart"
|
||||
|
||||
@@ -8,9 +7,6 @@ void subbrute_scene_load_select_callback(SubBruteCustomEvent event, void* contex
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_scene_load_select_callback");
|
||||
#endif
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, event);
|
||||
}
|
||||
|
||||
@@ -43,9 +39,14 @@ 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
|
||||
FURI_LOG_D(TAG, "load_index: %d", instance->device->load_index);
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "../views/subbrute_attack_view.h"
|
||||
#include "../helpers/subbrute_worker.h"
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteSceneRunAttack"
|
||||
|
||||
@@ -12,56 +10,25 @@ static void subbrute_scene_run_attack_callback(SubBruteCustomEvent event, void*
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, event);
|
||||
}
|
||||
|
||||
//static void subbrute_scene_run_attack_worker_callback(void* context) {
|
||||
// SubBruteState* instance = (SubBruteState*)context;
|
||||
//
|
||||
// if(instance->locked || instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// return;
|
||||
// }
|
||||
// instance->locked = true;
|
||||
//
|
||||
// if(subbrute_worker_can_manual_transmit(instance->worker)) {
|
||||
// // Blink
|
||||
// notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
// subbrute_device_create_packet_parsed(instance->device, instance->device->key_index, true);
|
||||
//
|
||||
//#ifdef FURI_DEBUG
|
||||
// FURI_LOG_I(TAG, "subbrute_worker_manual_transmit");
|
||||
//#endif
|
||||
// if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) {
|
||||
//#ifdef FURI_DEBUG
|
||||
// FURI_LOG_I(TAG, "transmit ok");
|
||||
//#endif
|
||||
// // Make payload for new iteration or exit
|
||||
// if(instance->device->key_index + 1 <= instance->device->max_value) {
|
||||
// instance->device->key_index++;
|
||||
// } else {
|
||||
// view_dispatcher_send_custom_event(
|
||||
// instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Stop
|
||||
// notification_message(instance->notifications, &sequence_blink_stop);
|
||||
// }
|
||||
//
|
||||
// instance->locked = false;
|
||||
// subbrute_attack_view_set_current_step(instance->view_attack, instance->device->key_index);
|
||||
//}
|
||||
static void
|
||||
subbrute_scene_run_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
|
||||
if(state == SubBruteWorkerStateIDLE) {
|
||||
// Can't be IDLE on this step!
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||
} else if(state == SubBruteWorkerStateFinished) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
}
|
||||
}
|
||||
void subbrute_scene_run_attack_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
// SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack);
|
||||
// furi_assert(state);
|
||||
//
|
||||
// furi_timer_free(state->timer);
|
||||
// free(state);
|
||||
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
subbrute_worker_stop(instance->worker);
|
||||
}
|
||||
subbrute_worker_stop(instance->worker);
|
||||
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
@@ -70,124 +37,67 @@ void subbrute_scene_run_attack_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
//
|
||||
// SubBruteAttackState* state = malloc(sizeof(SubBruteAttackState));
|
||||
// scene_manager_set_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack, (uint32_t)state);
|
||||
|
||||
instance->current_view = SubBruteViewAttack;
|
||||
subbrute_attack_view_set_callback(view, subbrute_scene_run_attack_callback, instance);
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, instance->current_view);
|
||||
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
(uint8_t)instance->device->attack,
|
||||
instance->device->max_value,
|
||||
instance->device->key_index,
|
||||
true);
|
||||
subbrute_worker_set_callback(
|
||||
instance->worker, subbrute_scene_run_attack_device_state_changed, instance);
|
||||
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
// Init Continuous worker with values!
|
||||
if(!subbrute_worker_start(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
furi_string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker Continuous init failed!");
|
||||
if(!subbrute_worker_is_running(instance->worker)) {
|
||||
subbrute_worker_set_step(instance->worker, instance->device->key_index);
|
||||
if(!subbrute_worker_start(instance->worker)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||
} else {
|
||||
notification_message(instance->notifications, &sequence_single_vibro);
|
||||
notification_message(instance->notifications, &sequence_blink_start_yellow);
|
||||
}
|
||||
} else {
|
||||
// Init worker with values
|
||||
if(!subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
furi_string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker init failed!");
|
||||
}
|
||||
|
||||
// state->timer = furi_timer_alloc(
|
||||
// subbrute_scene_run_attack_worker_callback, FuriTimerTypePeriodic, instance);
|
||||
// furi_timer_start(state->timer, pdMS_TO_TICKS(100)); // 20 ms
|
||||
}
|
||||
}
|
||||
|
||||
bool subbrute_scene_run_attack_on_event(void* context, SceneManagerEvent event) {
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
// SubBruteAttackState* state = (SubBruteAttackState*)scene_manager_get_scene_state(
|
||||
// instance->scene_manager, SubBruteSceneRunAttack);
|
||||
// furi_assert(state);
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
SubBruteAttackView* view = instance->view_attack;
|
||||
uint64_t step = subbrute_worker_get_step(instance->worker);
|
||||
instance->device->key_index = step;
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
|
||||
if(event.event == SubBruteCustomEventTypeTransmitNotStarted ||
|
||||
event.event == SubBruteCustomEventTypeTransmitFinished ||
|
||||
event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
// furi_timer_stop(state->timer);
|
||||
// Stop transmit
|
||||
if(event.event == SubBruteCustomEventTypeTransmitFinished) {
|
||||
notification_message(instance->notifications, &sequence_display_backlight_on);
|
||||
notification_message(instance->notifications, &sequence_single_vibro);
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
notification_message(instance->notifications, &sequence_double_vibro);
|
||||
|
||||
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
} else if(
|
||||
event.event == SubBruteCustomEventTypeTransmitNotStarted ||
|
||||
event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
if (subbrute_worker_is_running(instance->worker)) {
|
||||
// Notify
|
||||
notification_message(instance->notifications, &sequence_single_vibro);
|
||||
}
|
||||
// Stop transmit
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeError) {
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
|
||||
// Stop transmit
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
consumed = true;
|
||||
} 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->key_index);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subbrute_worker_get_continuous_worker(instance->worker)) {
|
||||
if(subbrute_worker_can_transmit(instance->worker)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index, true);
|
||||
|
||||
if(subbrute_worker_transmit(instance->worker, instance->device->payload)) {
|
||||
// Make payload for new iteration or exit
|
||||
if(instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// End of list
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
} else {
|
||||
instance->device->key_index++;
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeUpdateView);
|
||||
//subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
} else {
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker, false)) {
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_yellow_100);
|
||||
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index, true);
|
||||
|
||||
if(subbrute_worker_manual_transmit(instance->worker, instance->device->payload)) {
|
||||
// Make payload for new iteration or exit
|
||||
if(instance->device->key_index + 1 > instance->device->max_value) {
|
||||
// End of list
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeTransmitFinished);
|
||||
} else {
|
||||
instance->device->key_index++;
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, SubBruteCustomEventTypeUpdateView);
|
||||
//subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
}
|
||||
uint64_t step = subbrute_worker_get_step(instance->worker);
|
||||
instance->device->key_index = step;
|
||||
subbrute_attack_view_set_current_step(view, step);
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -1,34 +1,30 @@
|
||||
#include <subghz/types.h>
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <gui/modules/validators.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "subbrute_scene.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
|
||||
#define TAG "SubBruteSceneSaveFile"
|
||||
|
||||
void subbrute_scene_save_name_on_enter(void* context) {
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
SubBruteDevice* device = instance->device;
|
||||
|
||||
// Setup view
|
||||
TextInput* text_input = instance->text_input;
|
||||
set_random_name(device->text_store, sizeof(device->text_store));
|
||||
set_random_name(instance->text_store, sizeof(instance->text_store));
|
||||
|
||||
text_input_set_header_text(text_input, "Name of file");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
subbrute_text_input_callback,
|
||||
instance,
|
||||
device->text_store,
|
||||
instance->text_store,
|
||||
SUBBRUTE_MAX_LEN_NAME,
|
||||
true);
|
||||
|
||||
furi_string_set(device->load_path, SUBBRUTE_PATH);
|
||||
furi_string_reset(instance->file_path);
|
||||
furi_string_set_str(instance->file_path, SUBBRUTE_PATH);
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
furi_string_get_cstr(device->load_path), SUBBRUTE_FILE_EXT, "");
|
||||
furi_string_get_cstr(instance->file_path), SUBBRUTE_FILE_EXT, "");
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, SubBruteViewTextInput);
|
||||
@@ -45,18 +41,15 @@ bool subbrute_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
event.type == SceneManagerEventTypeCustom &&
|
||||
event.event == SubBruteCustomEventTypeTextEditDone) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Saving: %s", instance->device->text_store);
|
||||
FURI_LOG_D(TAG, "Saving: %s", instance->text_store);
|
||||
#endif
|
||||
bool success = false;
|
||||
if(strcmp(instance->device->text_store, "")) {
|
||||
if(strcmp(instance->text_store, "")) {
|
||||
furi_string_reset(instance->file_path);
|
||||
furi_string_cat_printf(
|
||||
instance->device->load_path,
|
||||
"/%s%s",
|
||||
instance->device->text_store,
|
||||
SUBBRUTE_FILE_EXT);
|
||||
instance->file_path, "%s/%s%s", SUBBRUTE_PATH, instance->text_store, SUBBRUTE_FILE_EXT);
|
||||
|
||||
if(subbrute_device_save_file(
|
||||
instance->device, furi_string_get_cstr(instance->device->load_path))) {
|
||||
if(subbrute_device_save_file(instance->device, furi_string_get_cstr(instance->file_path))) {
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveSuccess);
|
||||
success = true;
|
||||
consumed = true;
|
||||
@@ -82,5 +75,5 @@ void subbrute_scene_save_name_on_exit(void* context) {
|
||||
|
||||
text_input_reset(instance->text_input);
|
||||
|
||||
furi_string_reset(instance->device->load_path);
|
||||
furi_string_reset(instance->file_path);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
void subbrute_scene_save_success_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "../views/subbrute_attack_view.h"
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteSceneSetupAttack"
|
||||
|
||||
@@ -11,6 +10,18 @@ static void subbrute_scene_setup_attack_callback(SubBruteCustomEvent event, void
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, event);
|
||||
}
|
||||
|
||||
static void
|
||||
subbrute_scene_setup_attack_device_state_changed(void* context, SubBruteWorkerState state) {
|
||||
furi_assert(context);
|
||||
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
|
||||
if(state == SubBruteWorkerStateIDLE) {
|
||||
// Can't be IDLE on this step!
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, SubBruteCustomEventTypeError);
|
||||
}
|
||||
}
|
||||
|
||||
void subbrute_scene_setup_attack_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = (SubBruteState*)context;
|
||||
@@ -20,6 +31,14 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
||||
FURI_LOG_D(TAG, "Enter Attack: %d", instance->device->attack);
|
||||
#endif
|
||||
|
||||
subbrute_worker_set_callback(
|
||||
instance->worker, subbrute_scene_setup_attack_device_state_changed, context);
|
||||
|
||||
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,
|
||||
@@ -27,14 +46,6 @@ void subbrute_scene_setup_attack_on_enter(void* context) {
|
||||
instance->device->key_index,
|
||||
false);
|
||||
|
||||
if(!subbrute_worker_init_manual_transmit(
|
||||
instance->worker,
|
||||
instance->device->frequency,
|
||||
instance->device->preset,
|
||||
furi_string_get_cstr(instance->device->protocol_name))) {
|
||||
FURI_LOG_W(TAG, "Worker init failed!");
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -46,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_manual_transmit_stop(instance->worker);
|
||||
subbrute_worker_stop(instance->worker);
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
@@ -57,17 +68,9 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubBruteCustomEventTypeTransmitStarted) {
|
||||
subbrute_worker_set_continuous_worker(instance->worker, false);
|
||||
subbrute_attack_view_set_worker_type(view, false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeTransmitContinuousStarted) {
|
||||
// Setting different type of worker
|
||||
subbrute_worker_set_continuous_worker(instance->worker, true);
|
||||
subbrute_attack_view_set_worker_type(view, true);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneRunAttack);
|
||||
} else if(event.event == SubBruteCustomEventTypeSaveFile) {
|
||||
subbrute_worker_manual_transmit_stop(instance->worker);
|
||||
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
instance->device->attack,
|
||||
@@ -76,11 +79,6 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneSaveName);
|
||||
} else if(event.event == SubBruteCustomEventTypeBackPressed) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "SubBruteCustomEventTypeBackPressed");
|
||||
#endif
|
||||
instance->device->key_index = 0x00;
|
||||
//subbrute_attack_view_stop_worker(view);
|
||||
subbrute_attack_view_init_values(
|
||||
view,
|
||||
instance->device->attack,
|
||||
@@ -88,98 +86,49 @@ bool subbrute_scene_setup_attack_on_event(void* context, SceneManagerEvent event
|
||||
instance->device->key_index,
|
||||
false);
|
||||
scene_manager_next_scene(instance->scene_manager, SubBruteSceneStart);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUp) {
|
||||
// +1
|
||||
if((instance->device->key_index + 1) - instance->device->max_value == 1) {
|
||||
instance->device->key_index = 0x00;
|
||||
} else {
|
||||
uint64_t value = instance->device->key_index + 1;
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index = value;
|
||||
} else {
|
||||
instance->device->key_index = value % instance->device->max_value;
|
||||
}
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepUpMore) {
|
||||
// +50
|
||||
uint64_t value = instance->device->key_index + 50;
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index += value;
|
||||
} else {
|
||||
instance->device->key_index = value % instance->device->max_value;
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDown) {
|
||||
// -1
|
||||
if(instance->device->key_index - 1 == 0) {
|
||||
instance->device->key_index = 0x00;
|
||||
} else if(instance->device->key_index == 0) {
|
||||
instance->device->key_index = instance->device->max_value;
|
||||
} else {
|
||||
uint64_t value = ((instance->device->key_index - 1) + instance->device->max_value);
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index = value;
|
||||
} else {
|
||||
instance->device->key_index = value % instance->device->max_value;
|
||||
}
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeChangeStepDownMore) {
|
||||
// -50
|
||||
uint64_t value = ((instance->device->key_index - 50) + instance->device->max_value);
|
||||
if(value == instance->device->max_value) {
|
||||
instance->device->key_index = value;
|
||||
} else {
|
||||
instance->device->key_index = value % instance->device->max_value;
|
||||
}
|
||||
subbrute_attack_view_set_current_step(view, instance->device->key_index);
|
||||
} else if(event.event == SubBruteCustomEventTypeError) {
|
||||
notification_message(instance->notifications, &sequence_error);
|
||||
} else if(event.event == SubBruteCustomEventTypeTransmitCustom) {
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker, true)) {
|
||||
// We can transmit only in not working states
|
||||
if(subbrute_worker_can_manual_transmit(instance->worker)) {
|
||||
// MANUAL Transmit!
|
||||
// Blink
|
||||
notification_message(instance->notifications, &sequence_blink_green_100);
|
||||
|
||||
// if(!subbrute_attack_view_is_worker_running(view)) {
|
||||
// subbrute_attack_view_start_worker(
|
||||
// view,
|
||||
// instance->device->frequency,
|
||||
// instance->device->preset,
|
||||
// furi_string_get_cstr(instance->device->protocol_name));
|
||||
// }
|
||||
subbrute_device_create_packet_parsed(
|
||||
instance->device, instance->device->key_index, false);
|
||||
subbrute_worker_manual_transmit(instance->worker, instance->device->payload);
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// if(event.type == SceneManagerEventTypeCustom) {
|
||||
// switch(event.event) {
|
||||
// case SubBruteCustomEventTypeMenuSelected:
|
||||
// with_view_model(
|
||||
// view, (SubBruteMainViewModel * model) {
|
||||
// instance->menu_index = model->index;
|
||||
// return false;
|
||||
// });
|
||||
// scene_manager_next_scene(instance->scene_manager, SubBruteSceneLoadFile);
|
||||
// consumed = true;
|
||||
// break;
|
||||
// case SubBruteCustomEventTypeLoadFile:
|
||||
// with_view_model(
|
||||
// view, (SubBruteMainViewModel * model) {
|
||||
// instance->menu_index = model->index;
|
||||
// return false;
|
||||
// });
|
||||
// scene_manager_next_scene(instance->scene_manager, SubBruteSceneSetupAttack);
|
||||
// consumed = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
return consumed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include "../views/subbrute_main_view.h"
|
||||
#include "subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteSceneStart"
|
||||
|
||||
@@ -42,12 +41,24 @@ bool subbrute_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Event: %ld", event.event);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Event: %ld, SubBruteCustomEventTypeMenuSelected: %s, SubBruteCustomEventTypeLoadFile: %s",
|
||||
event.event,
|
||||
event.event == SubBruteCustomEventTypeMenuSelected ? "true" : "false",
|
||||
event.event == SubBruteCustomEventTypeLoadFile ? "true" : "false");
|
||||
#endif
|
||||
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;
|
||||
|
||||
@@ -1,56 +1,9 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/view_stack.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/loading.h>
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include "subbrute.h"
|
||||
#include "subbrute_i.h"
|
||||
#include "subbrute_custom_event.h"
|
||||
#include "scenes/subbrute_scene.h"
|
||||
|
||||
#define TAG "SubBruteApp"
|
||||
|
||||
static const char* subbrute_menu_names[] = {
|
||||
[SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz",
|
||||
[SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 12bit 868MHz",
|
||||
[SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 10bit 300MHz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 10bit 310MHz",
|
||||
[SubBruteAttackLoadFile] = "BF existing dump",
|
||||
[SubBruteAttackTotalCount] = "Total Count",
|
||||
};
|
||||
|
||||
static const char* subbrute_menu_names_small[] = {
|
||||
[SubBruteAttackCAME12bit303] = "CAME 303MHz",
|
||||
[SubBruteAttackCAME12bit307] = "CAME 307MHz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 433MHz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 868MHz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 433MHz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 868MHz",
|
||||
[SubBruteAttackChamberlain9bit300] = "Cham 300MHz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Cham 315MHz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Cham 390MHz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 300MHz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 310MHz",
|
||||
[SubBruteAttackLoadFile] = "Existing",
|
||||
[SubBruteAttackTotalCount] = "Total Count",
|
||||
};
|
||||
|
||||
static bool subbrute_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = context;
|
||||
@@ -72,6 +25,9 @@ static void subbrute_tick_event_callback(void* context) {
|
||||
SubBruteState* subbrute_alloc() {
|
||||
SubBruteState* instance = malloc(sizeof(SubBruteState));
|
||||
|
||||
memset(instance->text_store, 0, sizeof(instance->text_store));
|
||||
instance->file_path = furi_string_alloc();
|
||||
|
||||
instance->scene_manager = scene_manager_alloc(&subbrute_scene_handlers, instance);
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
|
||||
@@ -84,7 +40,7 @@ SubBruteState* subbrute_alloc() {
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
instance->view_dispatcher, subbrute_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
instance->view_dispatcher, subbrute_tick_event_callback, 10);
|
||||
instance->view_dispatcher, subbrute_tick_event_callback, 100);
|
||||
|
||||
//Dialog
|
||||
instance->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
@@ -95,7 +51,7 @@ SubBruteState* subbrute_alloc() {
|
||||
// Devices
|
||||
instance->device = subbrute_device_alloc();
|
||||
|
||||
// Worker
|
||||
// SubBruteWorker
|
||||
instance->worker = subbrute_worker_alloc();
|
||||
|
||||
// TextInput
|
||||
@@ -134,8 +90,6 @@ SubBruteState* subbrute_alloc() {
|
||||
SubBruteViewAttack,
|
||||
subbrute_attack_view_get_view(instance->view_attack));
|
||||
|
||||
// Loading
|
||||
instance->loading = loading_alloc();
|
||||
//instance->flipper_format = flipper_format_string_alloc();
|
||||
//instance->environment = subghz_environment_alloc();
|
||||
|
||||
@@ -146,124 +100,61 @@ void subbrute_free(SubBruteState* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
// SubBruteWorker
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteDevice");
|
||||
#endif
|
||||
subbrute_worker_stop(instance->worker);
|
||||
subbrute_worker_free(instance->worker);
|
||||
|
||||
// SubBruteDevice
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteDevice");
|
||||
#endif
|
||||
subbrute_device_free(instance->device);
|
||||
|
||||
// Notifications
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free Notifications");
|
||||
#endif
|
||||
notification_message(instance->notifications, &sequence_blink_stop);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
instance->notifications = NULL;
|
||||
|
||||
// Loading
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free loading");
|
||||
#endif
|
||||
loading_free(instance->loading);
|
||||
|
||||
// View Main
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewMain");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewMain);
|
||||
subbrute_main_view_free(instance->view_main);
|
||||
|
||||
// View Attack
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewAttack");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewAttack);
|
||||
subbrute_attack_view_free(instance->view_attack);
|
||||
|
||||
// TextInput
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewTextInput");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewTextInput);
|
||||
text_input_free(instance->text_input);
|
||||
|
||||
// Custom Widget
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewWidget");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewWidget);
|
||||
widget_free(instance->widget);
|
||||
|
||||
// Popup
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewPopup");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewPopup);
|
||||
popup_free(instance->popup);
|
||||
|
||||
// ViewStack
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free SubBruteViewStack");
|
||||
#endif
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, SubBruteViewStack);
|
||||
view_stack_free(instance->view_stack);
|
||||
|
||||
//Dialog
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free RECORD_DIALOGS");
|
||||
#endif
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
instance->dialogs = NULL;
|
||||
|
||||
// Scene manager
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free scene_manager");
|
||||
#endif
|
||||
scene_manager_free(instance->scene_manager);
|
||||
|
||||
// View Dispatcher
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free view_dispatcher");
|
||||
#endif
|
||||
view_dispatcher_free(instance->view_dispatcher);
|
||||
|
||||
// GUI
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free RECORD_GUI");
|
||||
#endif
|
||||
furi_record_close(RECORD_GUI);
|
||||
instance->gui = NULL;
|
||||
|
||||
furi_string_free(instance->file_path);
|
||||
|
||||
// The rest
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "free instance");
|
||||
#endif
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subbrute_show_loading_popup(void* context, bool show) {
|
||||
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
||||
SubBruteState* instance = context;
|
||||
ViewStack* view_stack = instance->view_stack;
|
||||
Loading* loading = instance->loading;
|
||||
|
||||
if(show) {
|
||||
// Raise timer priority so that animations can play
|
||||
vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
|
||||
view_stack_add_view(view_stack, loading_get_view(loading));
|
||||
} else {
|
||||
view_stack_remove_view(view_stack, loading_get_view(loading));
|
||||
// Restore default timer priority
|
||||
vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
void subbrute_text_input_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubBruteState* instance = context;
|
||||
@@ -278,18 +169,6 @@ void subbrute_popup_closed_callback(void* context) {
|
||||
instance->view_dispatcher, SubBruteCustomEventTypePopupClosed);
|
||||
}
|
||||
|
||||
const char* subbrute_get_menu_name(SubBruteAttacks index) {
|
||||
furi_assert(index < SubBruteAttackTotalCount);
|
||||
|
||||
return subbrute_menu_names[index];
|
||||
}
|
||||
|
||||
const char* subbrute_get_small_menu_name(SubBruteAttacks index) {
|
||||
furi_assert(index < SubBruteAttackTotalCount);
|
||||
|
||||
return subbrute_menu_names_small[index];
|
||||
}
|
||||
|
||||
// ENTRYPOINT
|
||||
int32_t subbrute_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
// Reserve first 100 events for button types and indexes, starting from 0
|
||||
SubBruteCustomEventTypeReserved = 100,
|
||||
@@ -10,7 +7,7 @@ typedef enum {
|
||||
SubBruteCustomEventTypeBackPressed,
|
||||
SubBruteCustomEventTypeIndexSelected,
|
||||
SubBruteCustomEventTypeTransmitStarted,
|
||||
SubBruteCustomEventTypeTransmitContinuousStarted,
|
||||
SubBruteCustomEventTypeError,
|
||||
SubBruteCustomEventTypeTransmitFinished,
|
||||
SubBruteCustomEventTypeTransmitNotStarted,
|
||||
SubBruteCustomEventTypeTransmitCustom,
|
||||
|
||||
@@ -1,85 +1,39 @@
|
||||
#include "subbrute_device.h"
|
||||
#include "subbrute_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_subghz.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <lib/subghz/types.h>
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <stream/stream.h>
|
||||
#include <stream/buffered_file_stream.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <lib/toolbox/stream/stream.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
#include <lib/flipper_format/flipper_format_i.h>
|
||||
|
||||
#define TAG "SubBruteDevice"
|
||||
|
||||
/**
|
||||
* List of protocols
|
||||
*/
|
||||
static const char* protocol_came = "CAME";
|
||||
static const char* protocol_cham_code = "Cham_Code";
|
||||
static const char* protocol_linear = "Linear";
|
||||
static const char* protocol_nice_flo = "Nice FLO";
|
||||
static const char* protocol_princeton = "Princeton";
|
||||
static const char* protocol_raw = "RAW";
|
||||
|
||||
/**
|
||||
* 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\n";
|
||||
static const char* subbrute_key_file_princeton_end = "%s\nKey: %s\nTE: %d\n";
|
||||
static const char* subbrute_key_small_no_tail = "Bit: %d\nKey: %s\n";
|
||||
static const char* subbrute_key_small_with_tail = "Bit: %d\nKey: %s\nTE: %d\n";
|
||||
|
||||
// Why nobody set in as const in all codebase?
|
||||
static const char* preset_ook270_async = "FuriHalSubGhzPresetOok270Async";
|
||||
static const char* preset_ook650_async = "FuriHalSubGhzPresetOok650Async";
|
||||
static const char* preset_2fsk_dev238_async = "FuriHalSubGhzPreset2FSKDev238Async";
|
||||
static const char* preset_2fsk_dev476_async = "FuriHalSubGhzPreset2FSKDev476Async";
|
||||
static const char* preset_msk99_97_kb_async = "FuriHalSubGhzPresetMSK99_97KbAsync";
|
||||
static const char* preset_gfs99_97_kb_async = "FuriHalSubGhzPresetGFS99_97KbAsync";
|
||||
|
||||
SubBruteDevice* subbrute_device_alloc() {
|
||||
SubBruteDevice* instance = malloc(sizeof(SubBruteDevice));
|
||||
|
||||
instance->state = SubBruteDeviceStateIDLE;
|
||||
instance->key_index = 0;
|
||||
|
||||
instance->load_path = furi_string_alloc();
|
||||
instance->preset_name = furi_string_alloc();
|
||||
instance->protocol_name = furi_string_alloc();
|
||||
|
||||
instance->protocol_info = NULL;
|
||||
instance->file_protocol_info = NULL;
|
||||
instance->decoder_result = NULL;
|
||||
instance->receiver = NULL;
|
||||
instance->environment = subghz_environment_alloc();
|
||||
|
||||
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit307);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433);
|
||||
#else
|
||||
subbrute_device_attack_set_default_values(instance, SubBruteAttackCAME12bit433);
|
||||
#endif
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subbrute_device_free(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_free");
|
||||
#endif
|
||||
|
||||
// I don't know how to free this
|
||||
instance->decoder_result = NULL;
|
||||
|
||||
if(instance->receiver != NULL) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subghz_receiver_free");
|
||||
#endif
|
||||
subghz_receiver_free(instance->receiver);
|
||||
instance->receiver = NULL;
|
||||
}
|
||||
@@ -87,57 +41,361 @@ void subbrute_device_free(SubBruteDevice* instance) {
|
||||
subghz_environment_free(instance->environment);
|
||||
instance->environment = NULL;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "before free");
|
||||
#endif
|
||||
|
||||
furi_string_free(instance->load_path);
|
||||
furi_string_free(instance->preset_name);
|
||||
furi_string_free(instance->protocol_name);
|
||||
subbrute_device_free_protocol_info(instance);
|
||||
|
||||
free(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;
|
||||
} else {
|
||||
uint64_t value = instance->key_index + step;
|
||||
if(value == instance->max_value) {
|
||||
instance->key_index = value;
|
||||
} else {
|
||||
instance->key_index = 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;
|
||||
} else {
|
||||
uint64_t value = ((instance->key_index + step) + instance->max_value);
|
||||
if(value == instance->max_value) {
|
||||
instance->key_index = value;
|
||||
} else {
|
||||
instance->key_index = value % instance->max_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instance->key_index;
|
||||
}
|
||||
|
||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* dev_file_name) {
|
||||
furi_assert(instance);
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_save_file: %s", dev_file_name);
|
||||
#endif
|
||||
bool result = subbrute_device_create_packet_parsed(instance, instance->key_index, false);
|
||||
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "subbrute_device_create_packet_parsed failed!");
|
||||
//subbrute_device_notification_message(instance, &sequence_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
Stream* stream = buffered_file_stream_alloc(storage);
|
||||
|
||||
result = false;
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
bool result = false;
|
||||
do {
|
||||
if(!buffered_file_stream_open(stream, dev_file_name, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) {
|
||||
buffered_file_stream_close(stream);
|
||||
if(!flipper_format_file_open_always(file, dev_file_name)) {
|
||||
FURI_LOG_E(TAG, "Failed to open file: %s", dev_file_name);
|
||||
break;
|
||||
}
|
||||
stream_write_cstring(stream, instance->payload);
|
||||
Stream* stream = flipper_format_get_raw_stream(file);
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
subbrute_protocol_file_generate_file(
|
||||
stream,
|
||||
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 {
|
||||
subbrute_protocol_default_generate_file(
|
||||
stream,
|
||||
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);
|
||||
}
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
buffered_file_stream_close(stream);
|
||||
stream_free(stream);
|
||||
if(!result) {
|
||||
FURI_LOG_E(TAG, "stream_write_string failed!");
|
||||
//subbrute_device_notification_message(instance, &sequence_error);
|
||||
FURI_LOG_E(TAG, "subbrute_device_save_file failed!");
|
||||
}
|
||||
|
||||
flipper_format_file_close(file);
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set: %d", type);
|
||||
#endif
|
||||
subbrute_device_attack_set_default_values(instance, type);
|
||||
|
||||
if(type != SubBruteAttackLoadFile) {
|
||||
subbrute_device_free_protocol_info(instance);
|
||||
instance->protocol_info = subbrute_protocol(type);
|
||||
}
|
||||
|
||||
// For non-file types we didn't set SubGhzProtocolDecoderBase
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
|
||||
uint8_t protocol_check_result = SubBruteFileResultProtocolNotFound;
|
||||
#ifdef FURI_DEBUG
|
||||
uint8_t bits;
|
||||
uint8_t te;
|
||||
uint8_t repeat;
|
||||
FuriHalSubGhzPreset preset;
|
||||
SubBruteFileProtocol file;
|
||||
#endif
|
||||
if(type != SubBruteAttackLoadFile) {
|
||||
instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||
instance->receiver, subbrute_protocol_file(instance->protocol_info->file));
|
||||
|
||||
if(!instance->decoder_result ||
|
||||
instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
|
||||
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);
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
bits = instance->protocol_info->bits;
|
||||
te = instance->protocol_info->te;
|
||||
repeat = instance->protocol_info->repeat;
|
||||
preset = instance->protocol_info->preset;
|
||||
file = instance->protocol_info->file;
|
||||
#endif
|
||||
} 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);
|
||||
#ifdef FURI_DEBUG
|
||||
bits = instance->file_protocol_info->bits;
|
||||
te = instance->file_protocol_info->te;
|
||||
repeat = instance->file_protocol_info->repeat;
|
||||
preset = instance->file_protocol_info->preset;
|
||||
file = instance->file_protocol_info->file;
|
||||
#endif
|
||||
}
|
||||
|
||||
subghz_receiver_free(instance->receiver);
|
||||
instance->receiver = NULL;
|
||||
|
||||
if(protocol_check_result != SubBruteFileResultOk) {
|
||||
return SubBruteFileResultProtocolNotFound;
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"subbrute_device_attack_set: %s, bits: %d, preset: %s, file: %s, te: %d, repeat: %d, max_value: %lld",
|
||||
subbrute_protocol_name(instance->attack),
|
||||
bits,
|
||||
subbrute_protocol_preset(preset),
|
||||
subbrute_protocol_file(file),
|
||||
te,
|
||||
repeat,
|
||||
instance->max_value);
|
||||
#endif
|
||||
|
||||
return SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, const char* file_path) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", file_path);
|
||||
#endif
|
||||
SubBruteFileResult result = SubBruteFileResultUnknown;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
|
||||
subbrute_device_free_protocol_info(instance);
|
||||
instance->file_protocol_info = malloc(sizeof(SubBruteProtocol));
|
||||
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||
result = SubBruteFileResultErrorOpenFile;
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
result = SubBruteFileResultMissingOrIncorrectHeader;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Frequency");
|
||||
result = SubBruteFileResultMissingOrIncorrectFrequency;
|
||||
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);
|
||||
}
|
||||
|
||||
const char* protocol_file = NULL;
|
||||
// Protocol
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
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->decoder_result =
|
||||
subghz_receiver_search_decoder_base_by_name(instance->receiver, protocol_file);
|
||||
|
||||
if(!instance->decoder_result || strcmp(protocol_file, "RAW") == 0) {
|
||||
FURI_LOG_E(TAG, "RAW unsupported");
|
||||
result = SubBruteFileResultProtocolNotSupported;
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
|
||||
FURI_LOG_E(TAG, "Protocol is dynamic - not supported");
|
||||
result = SubBruteFileResultDynamicProtocolNotValid;
|
||||
break;
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
else {
|
||||
FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Bit
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) {
|
||||
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
|
||||
}
|
||||
|
||||
// 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->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
|
||||
}
|
||||
|
||||
// TE
|
||||
if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect TE");
|
||||
//result = SubBruteFileResultMissingOrIncorrectTe;
|
||||
//break;
|
||||
} else {
|
||||
instance->file_protocol_info->te = temp_data32 != 0 ? temp_data32 : 0;
|
||||
}
|
||||
|
||||
// Repeat
|
||||
if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Repeat: %ld", temp_data32);
|
||||
#endif
|
||||
instance->file_protocol_info->repeat = (uint8_t)temp_data32;
|
||||
} else {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Repeat: 3 (default)");
|
||||
#endif
|
||||
instance->file_protocol_info->repeat = 3;
|
||||
}
|
||||
|
||||
result = SubBruteFileResultOk;
|
||||
} while(0);
|
||||
|
||||
furi_string_free(temp_str);
|
||||
flipper_format_file_close(fff_data_file);
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
subghz_receiver_free(instance->receiver);
|
||||
|
||||
instance->decoder_result = NULL;
|
||||
instance->receiver = NULL;
|
||||
|
||||
if(result == SubBruteFileResultOk) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Loaded successfully");
|
||||
#endif
|
||||
} else {
|
||||
subbrute_device_free_protocol_info(instance);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void subbrute_device_attack_set_default_values(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteAttacks default_attack) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values");
|
||||
#endif
|
||||
instance->attack = default_attack;
|
||||
instance->key_index = 0x00;
|
||||
instance->load_index = 0x00;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||
const char* result;
|
||||
switch(error_id) {
|
||||
@@ -174,9 +432,6 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||
case(SubBruteFileResultMissingOrIncorrectBit):
|
||||
result = "Missing or incorrect Bit";
|
||||
break;
|
||||
case(SubBruteFileResultBigBitSize):
|
||||
result = "Has more than 24 Bits";
|
||||
break;
|
||||
case(SubBruteFileResultMissingOrIncorrectKey):
|
||||
result = "Missing or incorrect Key";
|
||||
break;
|
||||
@@ -191,478 +446,11 @@ const char* subbrute_device_error_get_desc(SubBruteFileResult error_id) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool subbrute_device_create_packet_parsed(SubBruteDevice* instance, uint64_t step, bool small) {
|
||||
void subbrute_device_free_protocol_info(SubBruteDevice* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
//char step_payload[32];
|
||||
//memset(step_payload, '0', sizeof(step_payload));
|
||||
memset(instance->payload, 0, sizeof(instance->payload));
|
||||
FuriString* candidate = furi_string_alloc();
|
||||
|
||||
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]);
|
||||
} 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);
|
||||
instance->protocol_info = NULL;
|
||||
if(instance->file_protocol_info) {
|
||||
free(instance->file_protocol_info);
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "candidate: %s, step: %lld", furi_string_get_cstr(candidate), step);
|
||||
#endif
|
||||
|
||||
if(small) {
|
||||
if(instance->has_tail) {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_small_with_tail,
|
||||
instance->bit,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->te);
|
||||
} else {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_small_no_tail,
|
||||
instance->bit,
|
||||
furi_string_get_cstr(candidate));
|
||||
}
|
||||
} else {
|
||||
if(instance->has_tail) {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_princeton_end,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate),
|
||||
instance->te);
|
||||
} else {
|
||||
snprintf(
|
||||
instance->payload,
|
||||
sizeof(instance->payload),
|
||||
subbrute_key_file_key,
|
||||
instance->file_template,
|
||||
furi_string_get_cstr(candidate));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
//FURI_LOG_D(TAG, "payload: %s", instance->payload);
|
||||
#endif
|
||||
|
||||
furi_string_free(candidate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* instance, SubBruteAttacks type) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set: %d", type);
|
||||
#endif
|
||||
subbrute_device_attack_set_default_values(instance, type);
|
||||
switch(type) {
|
||||
case SubBruteAttackLoadFile:
|
||||
// In this case values must be already set
|
||||
// file_result =
|
||||
// subbrute_device_load_from_file(instance, furi_string_get_cstr(instance->load_path));
|
||||
// if(file_result != SubBruteFileResultOk) {
|
||||
// // Failed load file so failed to set attack type
|
||||
// return file_result; // RETURN
|
||||
// }
|
||||
break;
|
||||
case SubBruteAttackCAME12bit303:
|
||||
case SubBruteAttackCAME12bit307:
|
||||
case SubBruteAttackCAME12bit433:
|
||||
case SubBruteAttackCAME12bit868:
|
||||
if(type == SubBruteAttackCAME12bit303) {
|
||||
instance->frequency = 303875000;
|
||||
} else if(type == SubBruteAttackCAME12bit307) {
|
||||
instance->frequency = 307800000;
|
||||
} else if(type == SubBruteAttackCAME12bit433) {
|
||||
instance->frequency = 433920000;
|
||||
} else /* ALWAYS TRUE if(type == SubBruteAttackCAME12bit868) */ {
|
||||
instance->frequency = 868350000;
|
||||
}
|
||||
instance->bit = 12;
|
||||
furi_string_set_str(instance->protocol_name, protocol_came);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackChamberlain9bit300:
|
||||
case SubBruteAttackChamberlain9bit315:
|
||||
case SubBruteAttackChamberlain9bit390:
|
||||
if(type == SubBruteAttackChamberlain9bit300) {
|
||||
instance->frequency = 300000000;
|
||||
} else if(type == SubBruteAttackChamberlain9bit315) {
|
||||
instance->frequency = 315000000;
|
||||
} else /* ALWAYS TRUE if(type == SubBruteAttackChamberlain9bit390) */ {
|
||||
instance->frequency = 390000000;
|
||||
}
|
||||
instance->bit = 9;
|
||||
furi_string_set_str(instance->protocol_name, protocol_cham_code);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackLinear10bit300:
|
||||
instance->frequency = 300000000;
|
||||
instance->bit = 10;
|
||||
furi_string_set_str(instance->protocol_name, protocol_linear);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackLinear10bit310:
|
||||
instance->frequency = 310000000;
|
||||
instance->bit = 10;
|
||||
furi_string_set_str(instance->protocol_name, protocol_linear);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackNICE12bit433:
|
||||
instance->frequency = 433920000;
|
||||
instance->bit = 12;
|
||||
furi_string_set_str(instance->protocol_name, protocol_nice_flo);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
case SubBruteAttackNICE12bit868:
|
||||
instance->frequency = 868350000;
|
||||
instance->bit = 12;
|
||||
furi_string_set_str(instance->protocol_name, protocol_nice_flo);
|
||||
furi_string_set_str(instance->preset_name, preset_ook650_async);
|
||||
break;
|
||||
default:
|
||||
FURI_LOG_E(TAG, "Unknown attack type: %d", type);
|
||||
return SubBruteFileResultProtocolNotFound; // RETURN
|
||||
}
|
||||
|
||||
/*if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) {
|
||||
FURI_LOG_E(TAG, "Frequency invalid: %d", instance->frequency);
|
||||
return SubBruteFileResultMissingOrIncorrectFrequency; // RETURN
|
||||
}*/
|
||||
|
||||
// For non-file types we didn't set SubGhzProtocolDecoderBase
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
|
||||
uint8_t protocol_check_result = SubBruteFileResultProtocolNotFound;
|
||||
if(type != SubBruteAttackLoadFile) {
|
||||
instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||
instance->receiver, furi_string_get_cstr(instance->protocol_name));
|
||||
|
||||
if(!instance->decoder_result ||
|
||||
instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
|
||||
FURI_LOG_E(TAG, "Can't load SubGhzProtocolDecoderBase in phase non-file decoder set");
|
||||
} else {
|
||||
protocol_check_result = SubBruteFileResultOk;
|
||||
}
|
||||
} else {
|
||||
// And here we need to set preset enum
|
||||
instance->preset =
|
||||
subbrute_device_convert_preset(furi_string_get_cstr(instance->preset_name));
|
||||
protocol_check_result = SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
subghz_receiver_free(instance->receiver);
|
||||
instance->receiver = NULL;
|
||||
|
||||
if(protocol_check_result != SubBruteFileResultOk) {
|
||||
return SubBruteFileResultProtocolNotFound;
|
||||
}
|
||||
|
||||
instance->has_tail =
|
||||
(strcmp(furi_string_get_cstr(instance->protocol_name), protocol_princeton) == 0);
|
||||
|
||||
// Calc max value
|
||||
if(instance->attack == SubBruteAttackLoadFile) {
|
||||
instance->max_value = 0x3F;
|
||||
} else {
|
||||
FuriString* max_value_s;
|
||||
max_value_s = furi_string_alloc();
|
||||
for(uint8_t i = 0; i < instance->bit; 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->frequency,
|
||||
furi_string_get_cstr(instance->preset_name),
|
||||
furi_string_get_cstr(instance->protocol_name),
|
||||
instance->bit);
|
||||
// strncat(instance->file_template, "\n", sizeof(instance->file_template));
|
||||
// strncat(instance->file_template, subbrute_key_file_key, sizeof(instance->file_template));
|
||||
// if(instance->has_tail) {
|
||||
// strncat(
|
||||
// instance->file_template,
|
||||
// subbrute_key_file_princeton_end,
|
||||
// sizeof(instance->file_template));
|
||||
// }
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "tail: %d, file_template: %s", instance->has_tail, instance->file_template);
|
||||
#endif
|
||||
|
||||
// Init payload
|
||||
subbrute_device_create_packet_parsed(instance, instance->key_index, false);
|
||||
|
||||
return SubBruteFileResultOk;
|
||||
}
|
||||
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* instance, FuriString* file_path) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_load_from_file: %s", furi_string_get_cstr(file_path));
|
||||
#endif
|
||||
SubBruteFileResult result = SubBruteFileResultUnknown;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
|
||||
instance->receiver = subghz_receiver_alloc_init(instance->environment);
|
||||
subghz_receiver_set_filter(instance->receiver, SubGhzProtocolFlag_Decodable);
|
||||
furi_hal_subghz_reset();
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_path))) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", furi_string_get_cstr(file_path));
|
||||
result = SubBruteFileResultErrorOpenFile;
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
result = SubBruteFileResultMissingOrIncorrectHeader;
|
||||
break;
|
||||
}
|
||||
|
||||
// Frequency
|
||||
if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||
instance->frequency = temp_data32;
|
||||
if(!furi_hal_subghz_is_tx_allowed(instance->frequency)) {
|
||||
result = SubBruteFileResultFrequencyNotAllowed;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Frequency");
|
||||
result = SubBruteFileResultMissingOrIncorrectFrequency;
|
||||
break;
|
||||
}
|
||||
// Preset
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Preset FAIL");
|
||||
result = SubBruteFileResultPresetInvalid;
|
||||
} else {
|
||||
instance->preset_name = furi_string_alloc_set(furi_string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
// Protocol
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
result = SubBruteFileResultMissingProtocol;
|
||||
break;
|
||||
} else {
|
||||
instance->protocol_name = furi_string_alloc_set(furi_string_get_cstr(temp_str));
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Protocol: %s", furi_string_get_cstr(instance->protocol_name));
|
||||
#endif
|
||||
}
|
||||
|
||||
instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||
instance->receiver, furi_string_get_cstr(instance->protocol_name));
|
||||
|
||||
if(!instance->decoder_result ||
|
||||
strcmp(furi_string_get_cstr(instance->protocol_name), "RAW") == 0) {
|
||||
FURI_LOG_E(TAG, "RAW unsupported");
|
||||
result = SubBruteFileResultProtocolNotSupported;
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) {
|
||||
FURI_LOG_E(TAG, "Protocol is dynamic - not supported");
|
||||
result = SubBruteFileResultDynamicProtocolNotValid;
|
||||
break;
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
else {
|
||||
FURI_LOG_D(TAG, "Decoder: %s", instance->decoder_result->protocol->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
// instance->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||
// instance->receiver, furi_string_get_cstr(instance->protocol_name));
|
||||
//
|
||||
// if(!instance->decoder_result) {
|
||||
// FURI_LOG_E(TAG, "Protocol not found");
|
||||
// result = SubBruteFileResultProtocolNotFound;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// Bit
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Bit");
|
||||
result = SubBruteFileResultMissingOrIncorrectBit;
|
||||
break;
|
||||
} else {
|
||||
if(temp_data32 > 24) {
|
||||
FURI_LOG_E(TAG, "Incorrect Bits, 24 is maximum");
|
||||
result = SubBruteFileResultBigBitSize;
|
||||
break;
|
||||
}
|
||||
instance->bit = temp_data32;
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Bit: %ld", instance->bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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->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
|
||||
}
|
||||
|
||||
// TE
|
||||
if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect TE");
|
||||
//result = SubBruteFileResultMissingOrIncorrectTe;
|
||||
//break;
|
||||
} else {
|
||||
instance->te = temp_data32;
|
||||
instance->has_tail = true;
|
||||
}
|
||||
|
||||
// Repeat
|
||||
if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Repeat: %ld", temp_data32);
|
||||
#endif
|
||||
instance->repeat = temp_data32;
|
||||
} else {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Repeat: 3 (default)");
|
||||
#endif
|
||||
instance->repeat = 3;
|
||||
}
|
||||
|
||||
result = SubBruteFileResultOk;
|
||||
} while(0);
|
||||
|
||||
furi_string_free(temp_str);
|
||||
flipper_format_file_close(fff_data_file);
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
subghz_receiver_free(instance->receiver);
|
||||
|
||||
instance->decoder_result = NULL;
|
||||
instance->receiver = NULL;
|
||||
|
||||
if(result == SubBruteFileResultOk) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "Loaded successfully");
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void subbrute_device_attack_set_default_values(
|
||||
SubBruteDevice* instance,
|
||||
SubBruteAttacks default_attack) {
|
||||
furi_assert(instance);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "subbrute_device_attack_set_default_values");
|
||||
#endif
|
||||
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));
|
||||
memset(instance->text_store, 0, sizeof(instance->text_store));
|
||||
memset(instance->payload, 0, sizeof(instance->payload));
|
||||
|
||||
if(default_attack != SubBruteAttackLoadFile) {
|
||||
memset(instance->file_key, 0, sizeof(instance->file_key));
|
||||
|
||||
instance->max_value = (uint64_t)0x00;
|
||||
|
||||
furi_string_free(instance->protocol_name);
|
||||
furi_string_free(instance->preset_name);
|
||||
|
||||
furi_string_free(instance->load_path);
|
||||
instance->load_path = furi_string_alloc();
|
||||
|
||||
instance->protocol_name = furi_string_alloc_set(protocol_raw);
|
||||
instance->preset_name = furi_string_alloc_set(preset_ook650_async);
|
||||
instance->preset = FuriHalSubGhzPresetOok650Async;
|
||||
|
||||
instance->repeat = 5;
|
||||
instance->te = 0;
|
||||
instance->has_tail = false;
|
||||
}
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG, "subbrute_device_attack_set_default_values done. has_tail: %d", instance->has_tail);
|
||||
//furi_delay_ms(250);
|
||||
#endif
|
||||
}
|
||||
|
||||
FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset_name) {
|
||||
FuriString* preset;
|
||||
preset = furi_string_alloc_set(preset_name);
|
||||
FuriHalSubGhzPreset preset_value;
|
||||
if(furi_string_cmp_str(preset, preset_ook270_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPresetOok270Async;
|
||||
} else if(furi_string_cmp_str(preset, preset_ook650_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPresetOok650Async;
|
||||
} else if(furi_string_cmp_str(preset, preset_2fsk_dev238_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPreset2FSKDev238Async;
|
||||
} else if(furi_string_cmp_str(preset, preset_2fsk_dev476_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPreset2FSKDev476Async;
|
||||
} else if(furi_string_cmp_str(preset, preset_msk99_97_kb_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPresetMSK99_97KbAsync;
|
||||
} else if(furi_string_cmp_str(preset, preset_gfs99_97_kb_async) == 0) {
|
||||
preset_value = FuriHalSubGhzPresetMSK99_97KbAsync;
|
||||
} else {
|
||||
preset_value = FuriHalSubGhzPresetCustom;
|
||||
}
|
||||
|
||||
furi_string_free(preset);
|
||||
return preset_value;
|
||||
}
|
||||
instance->file_protocol_info = NULL;
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/toolbox/stream/stream.h>
|
||||
#include <gui/gui.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include "subbrute_protocols.h"
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
@@ -16,22 +14,6 @@
|
||||
|
||||
#define SUBBRUTE_PAYLOAD_SIZE 16
|
||||
|
||||
typedef enum {
|
||||
SubBruteAttackCAME12bit303,
|
||||
SubBruteAttackCAME12bit307,
|
||||
SubBruteAttackCAME12bit433,
|
||||
SubBruteAttackCAME12bit868,
|
||||
SubBruteAttackNICE12bit433,
|
||||
SubBruteAttackNICE12bit868,
|
||||
SubBruteAttackChamberlain9bit300,
|
||||
SubBruteAttackChamberlain9bit315,
|
||||
SubBruteAttackChamberlain9bit390,
|
||||
SubBruteAttackLinear10bit300,
|
||||
SubBruteAttackLinear10bit310,
|
||||
SubBruteAttackLoadFile,
|
||||
SubBruteAttackTotalCount,
|
||||
} SubBruteAttacks;
|
||||
|
||||
typedef enum {
|
||||
SubBruteFileResultUnknown,
|
||||
SubBruteFileResultOk,
|
||||
@@ -47,58 +29,42 @@ typedef enum {
|
||||
SubBruteFileResultMissingOrIncorrectBit,
|
||||
SubBruteFileResultMissingOrIncorrectKey,
|
||||
SubBruteFileResultMissingOrIncorrectTe,
|
||||
SubBruteFileResultBigBitSize,
|
||||
} SubBruteFileResult;
|
||||
|
||||
typedef enum {
|
||||
SubBruteDeviceStateIDLE,
|
||||
SubBruteDeviceStateReady,
|
||||
SubBruteDeviceStateTx,
|
||||
SubBruteDeviceStateFinished,
|
||||
} SubBruteDeviceState;
|
||||
|
||||
typedef struct {
|
||||
SubBruteDeviceState state;
|
||||
const SubBruteProtocol* protocol_info;
|
||||
SubBruteProtocol* file_protocol_info;
|
||||
|
||||
// Current step
|
||||
uint64_t key_index;
|
||||
FuriString* load_path;
|
||||
// Index of group to bruteforce in loaded file
|
||||
uint8_t load_index;
|
||||
|
||||
// SubGhz
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzProtocolDecoderBase* decoder_result;
|
||||
SubGhzEnvironment* environment;
|
||||
|
||||
// Attack state
|
||||
SubBruteAttacks attack;
|
||||
char file_template[SUBBRUTE_TEXT_STORE_SIZE];
|
||||
bool has_tail;
|
||||
char payload[SUBBRUTE_TEXT_STORE_SIZE * 2];
|
||||
uint64_t max_value;
|
||||
|
||||
// Loaded info for attack type
|
||||
FuriHalSubGhzPreset preset;
|
||||
FuriString* preset_name;
|
||||
FuriString* protocol_name;
|
||||
uint32_t frequency;
|
||||
uint32_t repeat;
|
||||
uint32_t bit;
|
||||
char current_key[SUBBRUTE_PAYLOAD_SIZE];
|
||||
uint32_t te;
|
||||
|
||||
char file_key[SUBBRUTE_MAX_LEN_NAME];
|
||||
char text_store[SUBBRUTE_PAYLOAD_SIZE];
|
||||
} SubBruteDevice;
|
||||
|
||||
SubBruteDevice* subbrute_device_alloc();
|
||||
void subbrute_device_free(SubBruteDevice* instance);
|
||||
|
||||
bool subbrute_device_save_file(SubBruteDevice* instance, const char* key_name);
|
||||
const char* subbrute_device_error_get_desc(SubBruteFileResult error_id);
|
||||
bool subbrute_device_create_packet_parsed(SubBruteDevice* context, uint64_t step, bool small);
|
||||
SubBruteFileResult subbrute_device_attack_set(SubBruteDevice* context, SubBruteAttacks type);
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, FuriString* file_path);
|
||||
FuriHalSubGhzPreset subbrute_device_convert_preset(const char* preset);
|
||||
uint8_t subbrute_device_load_from_file(SubBruteDevice* context, const char* file_path);
|
||||
|
||||
uint64_t subbrute_device_add_step(SubBruteDevice* instance, int8_t step);
|
||||
|
||||
void subbrute_device_free_protocol_info(SubBruteDevice* instance);
|
||||
void subbrute_device_attack_set_default_values(
|
||||
SubBruteDevice* context,
|
||||
SubBruteAttacks default_attack);
|
||||
@@ -4,12 +4,9 @@
|
||||
#include <furi_hal.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include "lib/toolbox/path.h"
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <lib/toolbox/stream/stream.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/view_stack.h>
|
||||
@@ -21,17 +18,12 @@
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/environment.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include "subbrute.h"
|
||||
#include "subbrute_device.h"
|
||||
#include "helpers/subbrute_worker.h"
|
||||
#include "subbrute.h"
|
||||
#include "scenes/subbrute_scene.h"
|
||||
#include "views/subbrute_attack_view.h"
|
||||
#include "views/subbrute_main_view.h"
|
||||
|
||||
@@ -56,7 +48,10 @@ struct SubBruteState {
|
||||
Popup* popup;
|
||||
Widget* widget;
|
||||
DialogsApp* dialogs;
|
||||
Loading* loading;
|
||||
|
||||
// Text store
|
||||
char text_store[SUBBRUTE_MAX_LEN_NAME];
|
||||
FuriString* file_path;
|
||||
|
||||
// Views
|
||||
SubBruteMainView* view_main;
|
||||
@@ -66,16 +61,12 @@ struct SubBruteState {
|
||||
// Scene
|
||||
SceneManager* scene_manager;
|
||||
|
||||
// SubBruteDevice
|
||||
SubBruteDevice* device;
|
||||
// SubBruteWorker
|
||||
SubBruteWorker* worker;
|
||||
|
||||
//Menu stuff
|
||||
// TODO: Do we need it?
|
||||
uint8_t menu_index;
|
||||
};
|
||||
|
||||
void subbrute_show_loading_popup(void* context, bool show);
|
||||
void subbrute_text_input_callback(void* context);
|
||||
void subbrute_popup_closed_callback(void* context);
|
||||
const char* subbrute_get_menu_name(uint8_t index);
|
||||
const char* subbrute_get_small_menu_name(uint8_t index);
|
||||
void subbrute_popup_closed_callback(void* context);
|
||||
@@ -0,0 +1,422 @@
|
||||
#include "subbrute_protocols.h"
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "SubBruteProtocols"
|
||||
|
||||
/**
|
||||
* CAME 12bit 303MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_came_12bit_303 = {
|
||||
.frequency = 303875000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = CAMEFileProtocol};
|
||||
|
||||
/**
|
||||
* CAME 12bit 307MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_came_12bit_307 = {
|
||||
.frequency = 307800000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = CAMEFileProtocol};
|
||||
|
||||
/**
|
||||
* CAME 12bit 433MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_came_12bit_433 = {
|
||||
.frequency = 433920000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = CAMEFileProtocol};
|
||||
|
||||
/**
|
||||
* CAME 12bit 868MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_came_12bit_868 = {
|
||||
.frequency = 868350000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = CAMEFileProtocol};
|
||||
|
||||
/**
|
||||
* NICE 12bit 433MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_nice_12bit_433 = {
|
||||
.frequency = 433920000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = NICEFileProtocol};
|
||||
|
||||
/**
|
||||
* NICE 12bit 868MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_nice_12bit_868 = {
|
||||
.frequency = 868350000,
|
||||
.bits = 12,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = NICEFileProtocol};
|
||||
|
||||
/**
|
||||
* Chamberlain 9bit 300MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_chamberlain_9bit_300 = {
|
||||
.frequency = 300000000,
|
||||
.bits = 9,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = ChamberlainFileProtocol};
|
||||
|
||||
/**
|
||||
* Chamberlain 9bit 315MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_chamberlain_9bit_315 = {
|
||||
.frequency = 315000000,
|
||||
.bits = 9,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = ChamberlainFileProtocol};
|
||||
|
||||
/**
|
||||
* Chamberlain 9bit 390MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_chamberlain_9bit_390 = {
|
||||
.frequency = 390000000,
|
||||
.bits = 9,
|
||||
.te = 0,
|
||||
.repeat = 3,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = ChamberlainFileProtocol};
|
||||
|
||||
/**
|
||||
* Linear 10bit 300MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_linear_10bit_300 = {
|
||||
.frequency = 300000000,
|
||||
.bits = 10,
|
||||
.te = 0,
|
||||
.repeat = 5,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = LinearFileProtocol};
|
||||
|
||||
/**
|
||||
* Linear 10bit 310MHz
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_linear_10bit_310 = {
|
||||
.frequency = 310000000,
|
||||
.bits = 10,
|
||||
.te = 0,
|
||||
.repeat = 5,
|
||||
.preset = FuriHalSubGhzPresetOok650Async,
|
||||
.file = LinearFileProtocol};
|
||||
|
||||
/**
|
||||
* BF existing dump
|
||||
*/
|
||||
const SubBruteProtocol subbrute_protocol_load_file =
|
||||
{0, 0, 0, 3, FuriHalSubGhzPresetOok650Async, RAWFileProtocol};
|
||||
|
||||
static const char* subbrute_protocol_names[] = {
|
||||
[SubBruteAttackCAME12bit303] = "CAME 12bit 303MHz",
|
||||
[SubBruteAttackCAME12bit307] = "CAME 12bit 307MHz",
|
||||
[SubBruteAttackCAME12bit433] = "CAME 12bit 433MHz",
|
||||
[SubBruteAttackCAME12bit868] = "CAME 12bit 868MHz",
|
||||
[SubBruteAttackNICE12bit433] = "NICE 12bit 433MHz",
|
||||
[SubBruteAttackNICE12bit868] = "NICE 12bit 868MHz",
|
||||
[SubBruteAttackChamberlain9bit300] = "Chamberlain 9bit 300MHz",
|
||||
[SubBruteAttackChamberlain9bit315] = "Chamberlain 9bit 315MHz",
|
||||
[SubBruteAttackChamberlain9bit390] = "Chamberlain 9bit 390MHz",
|
||||
[SubBruteAttackLinear10bit300] = "Linear 10bit 300MHz",
|
||||
[SubBruteAttackLinear10bit310] = "Linear 10bit 310MHz",
|
||||
[SubBruteAttackLoadFile] = "BF existing dump",
|
||||
[SubBruteAttackTotalCount] = "Total Count",
|
||||
};
|
||||
|
||||
static const char* subbrute_protocol_presets[] = {
|
||||
[FuriHalSubGhzPresetIDLE] = "FuriHalSubGhzPresetIDLE",
|
||||
[FuriHalSubGhzPresetOok270Async] = "FuriHalSubGhzPresetOok270Async",
|
||||
[FuriHalSubGhzPresetOok650Async] = "FuriHalSubGhzPresetOok650Async",
|
||||
[FuriHalSubGhzPreset2FSKDev238Async] = "FuriHalSubGhzPreset2FSKDev238Async",
|
||||
[FuriHalSubGhzPreset2FSKDev476Async] = "FuriHalSubGhzPreset2FSKDev476Async",
|
||||
[FuriHalSubGhzPresetMSK99_97KbAsync] = "FuriHalSubGhzPresetMSK99_97KbAsync",
|
||||
[FuriHalSubGhzPresetGFSK9_99KbAsync] = "FuriHalSubGhzPresetGFSK9_99KbAsync",
|
||||
};
|
||||
|
||||
const SubBruteProtocol* subbrute_protocol_registry[] = {
|
||||
[SubBruteAttackCAME12bit303] = &subbrute_protocol_came_12bit_303,
|
||||
[SubBruteAttackCAME12bit307] = &subbrute_protocol_came_12bit_307,
|
||||
[SubBruteAttackCAME12bit433] = &subbrute_protocol_came_12bit_433,
|
||||
[SubBruteAttackCAME12bit868] = &subbrute_protocol_came_12bit_868,
|
||||
[SubBruteAttackNICE12bit433] = &subbrute_protocol_nice_12bit_433,
|
||||
[SubBruteAttackNICE12bit868] = &subbrute_protocol_nice_12bit_868,
|
||||
[SubBruteAttackChamberlain9bit300] = &subbrute_protocol_chamberlain_9bit_300,
|
||||
[SubBruteAttackChamberlain9bit315] = &subbrute_protocol_chamberlain_9bit_315,
|
||||
[SubBruteAttackChamberlain9bit390] = &subbrute_protocol_chamberlain_9bit_390,
|
||||
[SubBruteAttackLinear10bit300] = &subbrute_protocol_linear_10bit_300,
|
||||
[SubBruteAttackLinear10bit310] = &subbrute_protocol_linear_10bit_310,
|
||||
[SubBruteAttackLoadFile] = &subbrute_protocol_load_file};
|
||||
|
||||
static const char* subbrute_protocol_file_types[] = {
|
||||
[CAMEFileProtocol] = "CAME",
|
||||
[NICEFileProtocol] = "Nice FLO",
|
||||
[ChamberlainFileProtocol] = "Cham_Code",
|
||||
[LinearFileProtocol] = "Linear",
|
||||
[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\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];
|
||||
}
|
||||
|
||||
const SubBruteProtocol* subbrute_protocol(SubBruteAttacks index) {
|
||||
return subbrute_protocol_registry[index];
|
||||
}
|
||||
|
||||
const char* subbrute_protocol_preset(FuriHalSubGhzPreset preset) {
|
||||
return subbrute_protocol_presets[preset];
|
||||
}
|
||||
|
||||
const char* subbrute_protocol_file(SubBruteFileProtocol protocol) {
|
||||
return subbrute_protocol_file_types[protocol];
|
||||
}
|
||||
|
||||
FuriHalSubGhzPreset subbrute_protocol_convert_preset(FuriString* preset_name) {
|
||||
for(size_t i = FuriHalSubGhzPresetIDLE; i < FuriHalSubGhzPresetCustom; i++) {
|
||||
if(furi_string_cmp_str(preset_name, subbrute_protocol_presets[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return FuriHalSubGhzPresetIDLE;
|
||||
}
|
||||
|
||||
SubBruteFileProtocol subbrute_protocol_file_protocol_name(FuriString* name) {
|
||||
for(size_t i = CAMEFileProtocol; i < TotalFileProtocol - 1; i++) {
|
||||
if(furi_string_cmp_str(name, subbrute_protocol_file_types[i]) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return RAWFileProtocol;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#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(
|
||||
stream,
|
||||
subbrute_key_small_with_tail,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream, subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||
}
|
||||
|
||||
furi_string_free(candidate);
|
||||
}
|
||||
|
||||
void subbrute_protocol_file_payload(
|
||||
Stream* stream,
|
||||
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();
|
||||
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
|
||||
stream_clean(stream);
|
||||
|
||||
if(te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_small_with_tail,
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream, subbrute_key_small_no_tail, bits, furi_string_get_cstr(candidate), repeat);
|
||||
}
|
||||
|
||||
furi_string_free(candidate);
|
||||
}
|
||||
|
||||
void subbrute_protocol_default_generate_file(
|
||||
Stream* stream,
|
||||
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
|
||||
stream_clean(stream);
|
||||
|
||||
if(te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_start_with_tail,
|
||||
frequency,
|
||||
subbrute_protocol_preset(preset),
|
||||
subbrute_protocol_file(file),
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_start_no_tail,
|
||||
frequency,
|
||||
subbrute_protocol_preset(preset),
|
||||
subbrute_protocol_file(file),
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
repeat);
|
||||
}
|
||||
|
||||
furi_string_free(candidate);
|
||||
}
|
||||
|
||||
void subbrute_protocol_file_generate_file(
|
||||
Stream* stream,
|
||||
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();
|
||||
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
|
||||
stream_clean(stream);
|
||||
if(te) {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_start_with_tail,
|
||||
frequency,
|
||||
subbrute_protocol_preset(preset),
|
||||
subbrute_protocol_file(file),
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
te,
|
||||
repeat);
|
||||
} else {
|
||||
stream_write_format(
|
||||
stream,
|
||||
subbrute_key_file_start_no_tail,
|
||||
frequency,
|
||||
subbrute_protocol_preset(preset),
|
||||
subbrute_protocol_file(file),
|
||||
bits,
|
||||
furi_string_get_cstr(candidate),
|
||||
repeat);
|
||||
}
|
||||
|
||||
furi_string_free(candidate);
|
||||
}
|
||||
|
||||
uint64_t subbrute_protocol_calc_max_value(SubBruteAttacks attack_type, uint8_t bits) {
|
||||
uint64_t max_value;
|
||||
if(attack_type == SubBruteAttackLoadFile) {
|
||||
max_value = 0xFF;
|
||||
} 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;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal_subghz.h>
|
||||
#include <core/string.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
//typedef enum {
|
||||
// FrequencyProtocolField,
|
||||
// BitsProtocolField,
|
||||
// HasTeProtocolField,
|
||||
// RepeatProtocolField,
|
||||
// PresetProtocolField,
|
||||
// FileProtocolField,
|
||||
// TotalProtocolFields
|
||||
//} ProtocolFields;
|
||||
|
||||
typedef enum {
|
||||
CAMEFileProtocol,
|
||||
NICEFileProtocol,
|
||||
ChamberlainFileProtocol,
|
||||
LinearFileProtocol,
|
||||
PrincetonFileProtocol,
|
||||
RAWFileProtocol,
|
||||
TotalFileProtocol,
|
||||
} SubBruteFileProtocol;
|
||||
|
||||
typedef enum {
|
||||
SubBruteAttackCAME12bit303,
|
||||
SubBruteAttackCAME12bit307,
|
||||
SubBruteAttackCAME12bit433,
|
||||
SubBruteAttackCAME12bit868,
|
||||
SubBruteAttackNICE12bit433,
|
||||
SubBruteAttackNICE12bit868,
|
||||
SubBruteAttackChamberlain9bit300,
|
||||
SubBruteAttackChamberlain9bit315,
|
||||
SubBruteAttackChamberlain9bit390,
|
||||
SubBruteAttackLinear10bit300,
|
||||
SubBruteAttackLinear10bit310,
|
||||
SubBruteAttackLoadFile,
|
||||
SubBruteAttackTotalCount,
|
||||
} SubBruteAttacks;
|
||||
|
||||
typedef struct {
|
||||
uint32_t frequency;
|
||||
uint8_t bits;
|
||||
uint8_t te;
|
||||
uint8_t repeat;
|
||||
FuriHalSubGhzPreset preset;
|
||||
SubBruteFileProtocol file;
|
||||
} SubBruteProtocol;
|
||||
|
||||
const SubBruteProtocol* subbrute_protocol(SubBruteAttacks index);
|
||||
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);
|
||||
|
||||
void subbrute_protocol_default_payload(
|
||||
Stream* stream,
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat);
|
||||
void subbrute_protocol_file_payload(
|
||||
Stream* stream,
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat,
|
||||
uint8_t load_index,
|
||||
const char* file_key);
|
||||
void subbrute_protocol_default_generate_file(
|
||||
Stream* stream,
|
||||
uint32_t frequency,
|
||||
FuriHalSubGhzPreset preset,
|
||||
SubBruteFileProtocol file,
|
||||
uint64_t step,
|
||||
uint8_t bits,
|
||||
uint8_t te,
|
||||
uint8_t repeat);
|
||||
void subbrute_protocol_file_generate_file(
|
||||
Stream* stream,
|
||||
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);
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "subbrute_attack_view.h"
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_protocols.h"
|
||||
|
||||
#include "assets_icons.h"
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/icon_i.h>
|
||||
#include <gui/icon_animation_i.h>
|
||||
#include <gui/icon.h>
|
||||
#include <gui/icon_animation.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define TAG "SubBruteAttackView"
|
||||
|
||||
@@ -292,69 +293,67 @@ 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 = 9; //
|
||||
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->width + icon_h_offset;
|
||||
const uint8_t icon_v_offset = icon->height; //
|
||||
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1;
|
||||
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;
|
||||
const uint8_t y = 0 + button_height;
|
||||
|
||||
canvas_draw_box(canvas, x, y, button_width, button_height);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG, "lbox, x: %d, y: %d, width: %d, height: %d", x, y, button_width, button_height);
|
||||
#endif
|
||||
// canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y + button_height - 0); //
|
||||
// canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y + button_height - 1);
|
||||
// canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y + button_height - 2);
|
||||
canvas_draw_box(canvas, x, y - button_height, button_width, button_height);
|
||||
canvas_draw_line(canvas, x + button_width + 0, y - button_height, x + button_width + 0, y - 1);
|
||||
canvas_draw_line(canvas, x + button_width + 1, y - button_height, x + button_width + 1, y - 2);
|
||||
canvas_draw_line(canvas, x + button_width + 2, y - button_height, x + button_width + 2, y - 3);
|
||||
|
||||
canvas_invert_color(canvas);
|
||||
canvas_draw_icon(canvas, x + horizontal_offset, y + icon_v_offset, icon);
|
||||
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, 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 = 9;
|
||||
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->width + icon_h_offset;
|
||||
const uint8_t icon_v_offset = icon->height; // + vertical_offset;
|
||||
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset + 1;
|
||||
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;
|
||||
const uint8_t y = 0 + button_height;
|
||||
|
||||
canvas_draw_box(canvas, x - button_width, y, button_width, button_height);
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"rbox, x: %d, y: %d, width: %d, height: %d",
|
||||
x - button_width,
|
||||
y,
|
||||
button_width,
|
||||
button_height);
|
||||
#endif
|
||||
// canvas_draw_line(canvas, x - button_width - 1, y, x + button_width - 1, y + button_height - 0);
|
||||
// canvas_draw_line(canvas, x - button_width - 2, y, x + button_width - 2, y + button_height - 1);
|
||||
// canvas_draw_line(canvas, x - button_width - 3, y, x + button_width - 3, y + button_height - 2);
|
||||
canvas_draw_box(canvas, x - button_width, y - button_height, button_width, button_height);
|
||||
canvas_draw_line(canvas, x - button_width - 1, y - button_height, x - button_width - 1, y - 1);
|
||||
canvas_draw_line(canvas, x - button_width - 2, y - button_height, x - button_width - 2, y - 2);
|
||||
canvas_draw_line(canvas, x - button_width - 3, y - button_height, x - button_width - 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->width, y + icon_v_offset, icon);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -364,7 +363,7 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) {
|
||||
char buffer[26];
|
||||
|
||||
const char* attack_name = NULL;
|
||||
attack_name = subbrute_get_menu_name(model->index);
|
||||
attack_name = subbrute_protocol_name(model->index);
|
||||
// Title
|
||||
if(model->is_attacking) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
@@ -393,8 +392,9 @@ void subbrute_attack_view_draw(Canvas* canvas, void* context) {
|
||||
}
|
||||
// canvas_draw_icon_animation
|
||||
const uint8_t icon_h_offset = 0;
|
||||
const uint8_t icon_width_with_offset = model->icon->icon->width + icon_h_offset;
|
||||
const uint8_t icon_v_offset = model->icon->icon->height; // + vertical_offset;
|
||||
const uint8_t icon_width_with_offset =
|
||||
icon_animation_get_width(model->icon) + icon_h_offset;
|
||||
const uint8_t icon_v_offset = icon_animation_get_height(model->icon); // + vertical_offset;
|
||||
const uint8_t x = canvas_width(canvas);
|
||||
const uint8_t y = canvas_height(canvas);
|
||||
canvas_draw_icon_animation(
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include <gui/view.h>
|
||||
#include "assets_icons.h"
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/icon.h>
|
||||
#include <subghz/types.h>
|
||||
#include "../subbrute_custom_event.h"
|
||||
|
||||
typedef void (*SubBruteAttackViewCallback)(SubBruteCustomEvent event, void* context);
|
||||
typedef struct SubBruteAttackView SubBruteAttackView;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "subbrute_main_view.h"
|
||||
#include "../subbrute_i.h"
|
||||
#include "../subbrute_protocols.h"
|
||||
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include "assets_icons.h"
|
||||
#include <gui/icon.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define STATUS_BAR_Y_SHIFT 14
|
||||
#define TAG "SubBruteMainView"
|
||||
@@ -85,12 +86,12 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) {
|
||||
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");
|
||||
canvas_draw_str_aligned(canvas, 64, 3, AlignCenter, AlignTop, "Sub-GHz BruteForcer v3");
|
||||
canvas_invert_color(canvas);
|
||||
|
||||
if(m->is_select_byte) {
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "key_field: %s", m->key_field);
|
||||
//FURI_LOG_D(TAG, "key_field: %s", m->key_field);
|
||||
#endif
|
||||
char msg_index[18];
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", m->index);
|
||||
@@ -117,13 +118,12 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) {
|
||||
const uint8_t item_height = 16;
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index);
|
||||
//FURI_LOG_D(TAG, "window_position: %d, index: %d", model->window_position, m->index);
|
||||
#endif
|
||||
for(uint8_t position = 0; position < SubBruteAttackTotalCount; ++position) {
|
||||
uint8_t item_position = position - model->window_position;
|
||||
|
||||
if(item_position < items_on_screen) {
|
||||
const char* str = subbrute_get_menu_name(position);
|
||||
if(m->index == position) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
@@ -131,7 +131,7 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) {
|
||||
9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
str);
|
||||
subbrute_protocol_name(position));
|
||||
elements_frame(
|
||||
canvas, 1, 1 + (item_position * item_height) + STATUS_BAR_Y_SHIFT, 124, 15);
|
||||
} else {
|
||||
@@ -141,7 +141,7 @@ void subbrute_main_view_draw(Canvas* canvas, SubBruteMainViewModel* model) {
|
||||
9 + (item_position * item_height) + STATUS_BAR_Y_SHIFT,
|
||||
AlignLeft,
|
||||
AlignCenter,
|
||||
str);
|
||||
subbrute_protocol_name(position));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
|
||||
#include "../subbrute_custom_event.h"
|
||||
#include <gui/view.h>
|
||||
#include "assets_icons.h"
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/icon.h>
|
||||
|
||||
typedef void (*SubBruteMainViewCallback)(SubBruteCustomEvent event, void* context);
|
||||
typedef struct SubBruteMainView SubBruteMainView;
|
||||
|
||||
Reference in New Issue
Block a user