forked from RogueMaster/flipperzero-firmware-wPlugins
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request RogueMaster#57 from Ganapati/dev
Add SubGhz Fuzzer
Showing
21 changed files
with
1,534 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,5 @@ App( | |
cdefines=["APP_FLIP_FRID"], | ||
requires=["gui"], | ||
stack_size=1 * 1024, | ||
order=29, | ||
order=13, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,5 +78,6 @@ App( | |
"wifi_scanner", | ||
"multi_converter", | ||
"flipfrid", | ||
"subbrute", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* ---------------------------------------------------------------------------- | ||
* "THE BEER-WARE LICENSE" (Revision 42): | ||
* @G4N4P4T1 wrote this file. As long as you retain this notice you | ||
* can do whatever you want with this stuff. If we meet some day, and you think | ||
* this stuff is worth it, you can buy me a beer in return. | ||
* ---------------------------------------------------------------------------- | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# FlipFrid | ||
|
||
SubGhz Fuzzer | ||
select your base message, the field to fuzz and let's get fuzzy ! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
App( | ||
appid="subbrute", | ||
name="SubGHz Bruteforcer", | ||
apptype=FlipperAppType.PLUGIN, | ||
entry_point="subbrute_start", | ||
cdefines=["APP_SUB_BRUTE"], | ||
requires=["gui","dialogs"], | ||
stack_size=2 * 1024, | ||
order=11, | ||
) |
198 changes: 198 additions & 0 deletions
198
applications/subbrute/scene/subbrute_scene_entrypoint.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
#include "subbrute_scene_entrypoint.h" | ||
#include "../subbrute_utils.h" | ||
|
||
string_t subbrute_menu_items[9]; | ||
|
||
void subbrute_scene_entrypoint_menu_callback(SubBruteState* context, uint32_t index) { | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
string_set_str(context->protocol, "RAW"); | ||
context->repeat = 5; | ||
context->te = 0; | ||
context->attack = index; | ||
switch(index) { | ||
case SubBruteAttackLoadFile: | ||
context->current_scene = SceneSelectFile; | ||
break; | ||
case SubBruteAttackCAME12bit433: | ||
context->frequency = 433920000; | ||
context->bit = 12; | ||
string_set_str(context->protocol, "CAME"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackCAME12bit868: | ||
context->frequency = 868350000; | ||
context->bit = 12; | ||
string_set_str(context->protocol, "CAME"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackChamberlain9bit315: | ||
context->frequency = 315000000; | ||
context->bit = 9; | ||
string_set_str(context->protocol, "Cham_Code"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
|
||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackChamberlain9bit390: | ||
context->frequency = 390000000; | ||
context->bit = 9; | ||
string_set_str(context->protocol, "Cham_Code"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
|
||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackLinear10bit300: | ||
context->frequency = 300000000; | ||
context->bit = 10; | ||
string_set_str(context->protocol, "Linear"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackLinear10bit310: | ||
context->frequency = 310000000; | ||
context->bit = 10; | ||
string_set_str(context->protocol, "Linear"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackNICE12bit433: | ||
context->frequency = 433920000; | ||
context->bit = 12; | ||
string_set_str(context->protocol, "Nice FLO"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
case SubBruteAttackNICE12bit868: | ||
context->frequency = 868350000; | ||
context->bit = 12; | ||
string_set_str(context->protocol, "Nice FLO"); | ||
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async"); | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
return; | ||
} | ||
context->current_scene = SceneAttack; | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void subbrute_scene_entrypoint_on_enter(SubBruteState* context) { | ||
// Clear the previous payload | ||
context->menu_index = 0; | ||
for(uint32_t i = 0; i < 9; i++) { | ||
string_init(subbrute_menu_items[i]); | ||
} | ||
|
||
string_set(subbrute_menu_items[0], "BF existing dump"); | ||
string_set(subbrute_menu_items[1], "CAME 12bit 433mhz"); | ||
string_set(subbrute_menu_items[2], "CAME 12bit 868mhz"); | ||
string_set(subbrute_menu_items[3], "Chamberlain 9bit 315mhz"); | ||
string_set(subbrute_menu_items[4], "Chamberlain 9bit 390mhz"); | ||
string_set(subbrute_menu_items[5], "Linear 10bit 300mhz"); | ||
string_set(subbrute_menu_items[6], "Linear 10bit 310mhz"); | ||
string_set(subbrute_menu_items[7], "NICE 12bit 433mhz"); | ||
string_set(subbrute_menu_items[8], "NICE 12bit 868mhz"); | ||
} | ||
|
||
void subbrute_scene_entrypoint_on_exit(SubBruteState* context) { | ||
UNUSED(context); | ||
for(uint32_t i = 0; i < 9; i++) { | ||
string_clear(subbrute_menu_items[i]); | ||
} | ||
} | ||
|
||
void subbrute_scene_entrypoint_on_tick(SubBruteState* context) { | ||
UNUSED(context); | ||
} | ||
|
||
void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context) { | ||
if(event.evt_type == EventTypeKey) { | ||
if(event.input_type == InputTypeShort) { | ||
switch(event.key) { | ||
case InputKeyDown: | ||
if(context->menu_index < SubBruteAttackNICE12bit868) { | ||
context->menu_index++; | ||
} | ||
break; | ||
case InputKeyUp: | ||
if(context->menu_index > SubBruteAttackLoadFile) { | ||
context->menu_index--; | ||
} | ||
break; | ||
case InputKeyLeft: | ||
case InputKeyRight: | ||
break; | ||
case InputKeyOk: | ||
subbrute_scene_entrypoint_menu_callback(context, context->menu_index); | ||
break; | ||
case InputKeyBack: | ||
context->is_running = false; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context) { | ||
canvas_clear(canvas); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Title | ||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "SubGHz Fuzzer"); | ||
|
||
if(context->menu_index > SubBruteAttackLoadFile) { | ||
canvas_set_font(canvas, FontSecondary); | ||
canvas_draw_str_aligned( | ||
canvas, | ||
64, | ||
24, | ||
AlignCenter, | ||
AlignTop, | ||
string_get_cstr(subbrute_menu_items[context->menu_index - 1])); | ||
} | ||
|
||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str_aligned( | ||
canvas, | ||
64, | ||
36, | ||
AlignCenter, | ||
AlignTop, | ||
string_get_cstr(subbrute_menu_items[context->menu_index])); | ||
|
||
if(context->menu_index < SubBruteAttackNICE12bit868) { | ||
canvas_set_font(canvas, FontSecondary); | ||
canvas_draw_str_aligned( | ||
canvas, | ||
64, | ||
48, | ||
AlignCenter, | ||
AlignTop, | ||
string_get_cstr(subbrute_menu_items[context->menu_index + 1])); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#pragma once | ||
#include "../subbrute.h" | ||
|
||
void subbrute_scene_entrypoint_on_enter(SubBruteState* context); | ||
void subbrute_scene_entrypoint_on_exit(SubBruteState* context); | ||
void subbrute_scene_entrypoint_on_tick(SubBruteState* context); | ||
void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context); | ||
void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
#include "subbrute_scene_load_file.h" | ||
#include "subbrute_scene_entrypoint.h" | ||
#include "../subbrute_utils.h" | ||
#include <lib/subghz/protocols/registry.h> | ||
|
||
#define SUBGHZ_APP_PATH_FOLDER "/ext/subghz" | ||
|
||
bool subbrute_load(SubBruteState* context, const char* file_path) { | ||
bool result = false; | ||
|
||
Storage* storage = furi_record_open(RECORD_STORAGE); | ||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); | ||
|
||
string_t temp_str; | ||
string_init(temp_str); | ||
uint32_t temp_data32; | ||
|
||
do { | ||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) { | ||
FURI_LOG_E(TAG, "Error open file %s", file_path); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Error open file"); | ||
break; | ||
} | ||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { | ||
FURI_LOG_E(TAG, "Missing or incorrect header"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Missing or incorrect header"); | ||
break; | ||
} | ||
// Frequency | ||
if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { | ||
FURI_LOG_I(TAG, "Frequency: %d", temp_data32); | ||
context->frequency = temp_data32; | ||
if(!subbrute_is_frequency_allowed(context)) { | ||
break; | ||
} | ||
} else { | ||
FURI_LOG_E(TAG, "Missing or incorrect Frequency"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Missing or incorrect Frequency"); | ||
break; | ||
} | ||
// Preset | ||
if(!flipper_format_read_string(fff_data_file, "Preset", context->preset)) { | ||
FURI_LOG_E(TAG, "Preset FAIL"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Preset FAIL"); | ||
} | ||
// Protocol | ||
if(!flipper_format_read_string(fff_data_file, "Protocol", context->protocol)) { | ||
FURI_LOG_E(TAG, "Missing Protocol"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Missing Protocol"); | ||
break; | ||
} else { | ||
FURI_LOG_I(TAG, "Protocol: %s", string_get_cstr(context->protocol)); | ||
} | ||
|
||
if(strcmp(string_get_cstr(context->protocol), "RAW") == 0) { | ||
FURI_LOG_E(TAG, "RAW unsupported"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "RAW unsupported"); | ||
break; | ||
} | ||
|
||
const SubGhzProtocol* registry = | ||
subghz_protocol_registry_get_by_name(string_get_cstr(context->protocol)); | ||
|
||
if(registry && registry->type == SubGhzProtocolTypeDynamic) { | ||
FURI_LOG_D(TAG, "Protocol is dynamic - not supported"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Dynamic protocol unsupported"); | ||
break; | ||
} | ||
|
||
context->decoder_result = subghz_receiver_search_decoder_base_by_name( | ||
context->receiver, string_get_cstr(context->protocol)); | ||
|
||
if(context->decoder_result) { | ||
FURI_LOG_I(TAG, "Found decoder"); | ||
} else { | ||
FURI_LOG_E(TAG, "Protocol not found"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Protocol not found"); | ||
break; | ||
} | ||
|
||
// Bit | ||
if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) { | ||
FURI_LOG_E(TAG, "Missing or incorrect Bit"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Missing or incorrect Bit"); | ||
break; | ||
} else { | ||
FURI_LOG_I(TAG, "Bit: %d", temp_data32); | ||
context->bit = temp_data32; | ||
} | ||
|
||
// Key | ||
if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) { | ||
FURI_LOG_E(TAG, "Missing or incorrect Key"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "Missing or incorrect Key"); | ||
break; | ||
} else { | ||
FURI_LOG_I(TAG, "Key: %s", string_get_cstr(temp_str)); | ||
string_set(context->key, string_get_cstr(temp_str)); | ||
} | ||
|
||
// TE | ||
if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) { | ||
FURI_LOG_E(TAG, "Missing or incorrect TE"); | ||
//string_reset(context->notification_msg); | ||
//string_set_str(context->notification_msg, "Missing or incorrect TE"); | ||
//break; | ||
} else { | ||
FURI_LOG_I(TAG, "TE: %d", temp_data32); | ||
context->te = temp_data32; | ||
} | ||
|
||
// Repeat | ||
if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) { | ||
FURI_LOG_I(TAG, "Repeat: %d", temp_data32); | ||
context->repeat = temp_data32; | ||
} else { | ||
FURI_LOG_I(TAG, "Repeat: 3 (default)"); | ||
context->repeat = 3; | ||
} | ||
|
||
result = true; | ||
} while(0); | ||
|
||
string_clear(temp_str); | ||
flipper_format_file_close(fff_data_file); | ||
flipper_format_free(fff_data_file); | ||
if(result) { | ||
FURI_LOG_I(TAG, "Loaded successfully"); | ||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, "File looks ok."); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
void subbrute_scene_load_file_on_enter(SubBruteState* context) { | ||
if(subbrute_load_protocol_from_file(context)) { | ||
context->current_scene = SceneSelectField; | ||
} else { | ||
subbrute_scene_entrypoint_on_enter(context); | ||
context->current_scene = SceneEntryPoint; | ||
} | ||
} | ||
|
||
void subbrute_scene_load_file_on_exit(SubBruteState* context) { | ||
UNUSED(context); | ||
} | ||
|
||
void subbrute_scene_load_file_on_tick(SubBruteState* context) { | ||
UNUSED(context); | ||
} | ||
|
||
void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context) { | ||
UNUSED(context); | ||
if(event.evt_type == EventTypeKey) { | ||
if(event.input_type == InputTypeShort) { | ||
switch(event.key) { | ||
case InputKeyDown: | ||
case InputKeyUp: | ||
case InputKeyLeft: | ||
case InputKeyRight: | ||
case InputKeyOk: | ||
break; | ||
case InputKeyBack: | ||
context->current_scene = SceneEntryPoint; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context) { | ||
UNUSED(context); | ||
canvas_clear(canvas); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Frame | ||
//canvas_draw_frame(canvas, 0, 0, 128, 64); | ||
|
||
// Title | ||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignTop, "SubGHz Fuzzer"); | ||
canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "Error: Press back"); | ||
} | ||
|
||
bool subbrute_load_protocol_from_file(SubBruteState* context) { | ||
string_t file_path; | ||
string_init(file_path); | ||
string_set_str(file_path, SUBGHZ_APP_PATH_FOLDER); | ||
|
||
// Input events and views are managed by file_select | ||
bool res = dialog_file_browser_show( | ||
context->dialogs, file_path, file_path, SUBGHZ_APP_EXTENSION, true, &I_sub1_10px, true); | ||
|
||
if(res) { | ||
res = subbrute_load(context, string_get_cstr(file_path)); | ||
} | ||
|
||
string_clear(file_path); | ||
|
||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#include "../subbrute.h" | ||
|
||
void subbrute_scene_load_file_on_enter(SubBruteState* context); | ||
void subbrute_scene_load_file_on_exit(SubBruteState* context); | ||
void subbrute_scene_load_file_on_tick(SubBruteState* context); | ||
void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context); | ||
void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context); | ||
bool subbrute_load_protocol_from_file(SubBruteState* context); |
320 changes: 320 additions & 0 deletions
320
applications/subbrute/scene/subbrute_scene_run_attack.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,320 @@ | ||
#include "subbrute_scene_run_attack.h" | ||
#include <lib/subghz/transmitter.h> | ||
#include <gui/elements.h> | ||
|
||
uint64_t subbrute_counter = 0; | ||
uint64_t max_value; | ||
bool locked = false; | ||
bool toSave = false; | ||
char subbrute_payload_byte[4]; | ||
#define SUBBRUTE_DELAY 1 | ||
|
||
FuriHalSubGhzPreset str_to_preset(string_t preset) { | ||
if(string_cmp_str(preset, "FuriHalSubGhzPresetOok270Async") == 0) { | ||
return FuriHalSubGhzPresetOok270Async; | ||
} | ||
if(string_cmp_str(preset, "FuriHalSubGhzPresetOok650Async") == 0) { | ||
return FuriHalSubGhzPresetOok650Async; | ||
} | ||
if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev238Async") == 0) { | ||
return FuriHalSubGhzPreset2FSKDev238Async; | ||
} | ||
if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev476Async") == 0) { | ||
return FuriHalSubGhzPreset2FSKDev476Async; | ||
} | ||
if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { | ||
return FuriHalSubGhzPresetMSK99_97KbAsync; | ||
} | ||
if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) { | ||
return FuriHalSubGhzPresetMSK99_97KbAsync; | ||
} | ||
return FuriHalSubGhzPresetCustom; | ||
} | ||
|
||
void subbrute_emit(SubBruteState* context) { | ||
//FURI_LOG_D(TAG, string_get_cstr(context->flipper_format_string)); | ||
|
||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, context->transmitter); | ||
while(!(furi_hal_subghz_is_async_tx_complete())) { | ||
furi_delay_ms(5); | ||
} | ||
|
||
furi_hal_subghz_stop_async_tx(); | ||
furi_hal_subghz_idle(); | ||
} | ||
|
||
void prepare_emit(SubBruteState* context) { | ||
furi_hal_subghz_init(); | ||
|
||
context->transmitter = | ||
subghz_transmitter_alloc_init(context->environment, string_get_cstr(context->protocol)); | ||
|
||
furi_hal_subghz_reset(); | ||
furi_hal_subghz_load_preset(str_to_preset(context->preset)); | ||
|
||
furi_hal_subghz_set_frequency_and_path(context->frequency); | ||
} | ||
|
||
void clear_emit(SubBruteState* context) { | ||
furi_hal_subghz_stop_async_tx(); | ||
furi_hal_subghz_sleep(); | ||
|
||
subghz_transmitter_free(context->transmitter); | ||
} | ||
/* | ||
void subbrute_send_raw_packet(SubBruteState* context) { | ||
string_reset(context->candidate); | ||
// Payload to padded binary string | ||
int* binaryNum = (int*)malloc(sizeof(int) * context->bit); | ||
uint32_t i = 0; | ||
for(i = 0; i < context->bit; i++) { | ||
binaryNum[i] = 0; | ||
} | ||
i = 0; | ||
uint64_t counter = context->payload; | ||
while(counter > 0) { | ||
binaryNum[i] = counter % 2; | ||
counter = counter / 2; | ||
i++; | ||
} | ||
// printing binary array in reverse order and build raw payload | ||
for(uint32_t loop = 0; loop < context->repeat; loop++) { | ||
for(int j = (int)context->bit - 1; j >= 0; j--) { | ||
if(binaryNum[j] == 1) { | ||
string_cat(context->candidate, context->subbrute_raw_one); | ||
} else { | ||
string_cat(context->candidate, context->subbrute_raw_zero); | ||
} | ||
} | ||
string_cat(context->candidate, context->subbrute_raw_stop); | ||
} | ||
free(binaryNum); | ||
string_init_printf( | ||
context->flipper_format_string, | ||
"Filetype: Flipper SubGhz RAW File\n" | ||
"Version: 1\n" | ||
"Frequency: %d\n" | ||
"Preset: %s\n" | ||
"Protocol: RAW\n" | ||
"RAW_Data: %s", | ||
context->frequency, | ||
string_get_cstr(context->preset), | ||
string_get_cstr(context->candidate)); | ||
subbrute_emit(context); | ||
} | ||
*/ | ||
void subbrute_send_packet_parsed(SubBruteState* context) { | ||
if(context->attack == SubBruteAttackLoadFile) { | ||
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)context->payload); | ||
string_replace_at(context->candidate, context->str_index, 3, subbrute_payload_byte); | ||
} else { | ||
string_t buffer; | ||
string_init(buffer); | ||
string_init_printf(buffer, "%16X", context->payload); | ||
int j = 0; | ||
string_set_str(context->candidate, " "); | ||
for(uint8_t i = 0; i < 16; i++) { | ||
if(string_get_char(buffer, i) != ' ') { | ||
string_set_char(context->candidate, i + j, string_get_char(buffer, i)); | ||
} else { | ||
string_set_char(context->candidate, i + j, '0'); | ||
} | ||
if(i % 2 != 0) { | ||
j++; | ||
} | ||
} | ||
string_clear(buffer); | ||
} | ||
if(strcmp(string_get_cstr(context->protocol), "Princeton") == 0) { | ||
string_init_printf( | ||
context->flipper_format_string, | ||
"Filetype: Flipper SubGhz Key File\n" | ||
"Version: 1\n" | ||
"Frequency: %u\n" | ||
"Preset: %s\n" | ||
"Protocol: %s\n" | ||
"Bit: %d\n" | ||
"Key: %s\n" | ||
"TE: %d\n", | ||
context->frequency, | ||
string_get_cstr(context->preset), | ||
string_get_cstr(context->protocol), | ||
context->bit, | ||
string_get_cstr(context->candidate), | ||
context->te); | ||
} else { | ||
string_init_printf( | ||
context->flipper_format_string, | ||
"Filetype: Flipper SubGhz Key File\n" | ||
"Version: 1\n" | ||
"Frequency: %u\n" | ||
"Preset: %s\n" | ||
"Protocol: %s\n" | ||
"Bit: %d\n" | ||
"Key: %s\n", | ||
context->frequency, | ||
string_get_cstr(context->preset), | ||
string_get_cstr(context->protocol), | ||
context->bit, | ||
string_get_cstr(context->candidate)); | ||
} | ||
|
||
stream_clean(context->stream); | ||
stream_write_string(context->stream, context->flipper_format_string); | ||
subghz_transmitter_deserialize(context->transmitter, context->flipper_format); | ||
|
||
subbrute_emit(context); | ||
} | ||
|
||
void subbrute_send_packet(SubBruteState* context) { | ||
///if(string_cmp_str(context->protocol, "RAW") == 0) { | ||
// subbrute_send_raw_packet(context); | ||
//} else { | ||
subbrute_send_packet_parsed(context); | ||
//} | ||
string_clear(context->flipper_format_string); | ||
} | ||
|
||
void subbrute_scene_run_attack_on_enter(SubBruteState* context) { | ||
if(!toSave) { | ||
if(context->attack == SubBruteAttackLoadFile) { | ||
max_value = 0xFF; | ||
} else { | ||
string_t max_value_s; | ||
string_init(max_value_s); | ||
for(uint8_t i = 0; i < context->bit; i++) { | ||
string_cat_printf(max_value_s, "1"); | ||
} | ||
max_value = (uint64_t)strtol(string_get_cstr(max_value_s), NULL, 2); | ||
string_clear(max_value_s); | ||
} | ||
context->str_index = (context->key_index * 3); | ||
string_init_set(context->candidate, context->key); | ||
context->flipper_format = flipper_format_string_alloc(); | ||
context->stream = flipper_format_get_raw_stream(context->flipper_format); | ||
context->environment = subghz_environment_alloc(); | ||
context->transmitter = subghz_transmitter_alloc_init( | ||
context->environment, string_get_cstr(context->protocol)); | ||
prepare_emit(context); | ||
} else { | ||
toSave = false; | ||
} | ||
} | ||
|
||
void subbrute_scene_run_attack_on_exit(SubBruteState* context) { | ||
if(!toSave) { | ||
clear_emit(context); | ||
} | ||
} | ||
|
||
void subbrute_scene_run_attack_on_tick(SubBruteState* context) { | ||
if(!context->is_attacking || locked) { | ||
return; | ||
} | ||
if(0 != subbrute_counter) { | ||
locked = true; | ||
subbrute_send_packet(context); | ||
|
||
if(context->payload == max_value) { | ||
context->payload = 0x00; | ||
subbrute_counter = 0; | ||
context->is_attacking = false; | ||
notification_message(context->notify, &sequence_blink_stop); | ||
notification_message(context->notify, &sequence_single_vibro); | ||
} else { | ||
context->payload++; | ||
} | ||
locked = false; | ||
} | ||
if(subbrute_counter > SUBBRUTE_DELAY) { | ||
subbrute_counter = 0; | ||
} else { | ||
subbrute_counter++; | ||
} | ||
} | ||
|
||
void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context) { | ||
if(event.evt_type == EventTypeKey) { | ||
if(event.input_type == InputTypeShort) { | ||
switch(event.key) { | ||
case InputKeyDown: | ||
if(!context->is_attacking) { | ||
toSave = true; | ||
context->current_scene = SceneSaveName; | ||
} | ||
case InputKeyUp: | ||
break; | ||
case InputKeyLeft: | ||
if(!context->is_attacking && context->payload > 0x00) { | ||
context->payload--; | ||
subbrute_send_packet(context); | ||
notification_message(context->notify, &sequence_blink_blue_10); | ||
} | ||
break; | ||
case InputKeyRight: | ||
if(!context->is_attacking && context->payload < max_value) { | ||
context->payload++; | ||
subbrute_send_packet(context); | ||
notification_message(context->notify, &sequence_blink_blue_10); | ||
} | ||
break; | ||
case InputKeyOk: | ||
if(!context->is_attacking) { | ||
context->is_attacking = true; | ||
notification_message(context->notify, &sequence_blink_start_blue); | ||
} else { | ||
context->is_attacking = false; | ||
notification_message(context->notify, &sequence_blink_stop); | ||
notification_message(context->notify, &sequence_single_vibro); | ||
} | ||
break; | ||
case InputKeyBack: | ||
locked = false; | ||
context->is_attacking = false; | ||
string_reset(context->notification_msg); | ||
context->payload = 0x00; | ||
subbrute_counter = 0; | ||
notification_message(context->notify, &sequence_blink_stop); | ||
if(context->attack == SubBruteAttackLoadFile) { | ||
context->current_scene = SceneSelectField; | ||
} else { | ||
context->current_scene = SceneEntryPoint; | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context) { | ||
canvas_clear(canvas); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Frame | ||
//canvas_draw_frame(canvas, 0, 0, 128, 64); | ||
|
||
// Title | ||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignTop, "Fire in the hole!"); | ||
|
||
char msg_index[26]; | ||
snprintf( | ||
msg_index, sizeof(msg_index), "< %04d / %04d >", (int)context->payload, (int)max_value); | ||
|
||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, msg_index); | ||
|
||
canvas_set_font(canvas, FontSecondary); | ||
char start_stop_msg[20]; | ||
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press (V) to save "); | ||
if(context->is_attacking) { | ||
elements_button_center(canvas, "Stop"); | ||
} else { | ||
elements_button_center(canvas, "Start"); | ||
} | ||
canvas_draw_str_aligned(canvas, 64, 39, AlignCenter, AlignTop, start_stop_msg); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#include "../subbrute.h" | ||
|
||
void subbrute_scene_run_attack_on_enter(SubBruteState* context); | ||
void subbrute_scene_run_attack_on_exit(SubBruteState* context); | ||
void subbrute_scene_run_attack_on_tick(SubBruteState* context); | ||
void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context); | ||
void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context); | ||
void send_packet(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
#include "../subbrute.h" | ||
#include "m-string.h" | ||
#include "subghz/types.h" | ||
#include <lib/toolbox/random_name.h> | ||
#include <gui/modules/validators.h> | ||
#include <lib/toolbox/path.h> | ||
|
||
#define MAX_TEXT_INPUT_LEN 22 | ||
|
||
bool backpressed = false; | ||
|
||
bool subbrute_path_is_file(string_t path) { | ||
return string_end_with_str_p(path, ".sub"); | ||
} | ||
// method modified from subghz_i.c | ||
// https://github.com/flipperdevices/flipperzero-firmware/blob/b0daa601ad5b87427a45f9089c8b403a01f72c2a/applications/subghz/subghz_i.c#L417-L456 | ||
bool subbrute_save_protocol_to_file(Stream* flipper_format_stream, const char* dev_file_name) { | ||
furi_assert(dev_file_name); | ||
|
||
Storage* storage = furi_record_open(RECORD_STORAGE); | ||
|
||
bool saved = false; | ||
string_t file_dir; | ||
string_init(file_dir); | ||
|
||
path_extract_dirname(dev_file_name, file_dir); | ||
do { | ||
if(!storage_simply_mkdir(storage, string_get_cstr(file_dir))) { | ||
FURI_LOG_E(TAG, "(save) Cannot mkdir"); | ||
break; | ||
} | ||
|
||
if(!storage_simply_remove(storage, dev_file_name)) { | ||
FURI_LOG_E(TAG, "(save) Cannot remove"); | ||
break; | ||
} | ||
|
||
stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); | ||
stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); | ||
|
||
saved = true; | ||
FURI_LOG_D(TAG, "(save) OK Save"); | ||
} while(0); | ||
string_clear(file_dir); | ||
furi_record_close(RECORD_STORAGE); | ||
return saved; | ||
} | ||
|
||
void custom_callback(SubBruteState* context) { | ||
if(strcmp(context->file_name_tmp, "")) { | ||
string_cat_printf(context->file_path, "/%s%s", context->file_name_tmp, ".sub"); | ||
if(subbrute_path_is_file(context->file_path_tmp)) { | ||
context->current_scene = SceneAttack; | ||
return; //false; | ||
|
||
} else { | ||
subbrute_save_protocol_to_file(context->stream, string_get_cstr(context->file_path)); | ||
} | ||
|
||
string_set_str(context->file_path, EXT_PATH("subghz")); | ||
string_reset(context->file_path_tmp); | ||
|
||
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); | ||
context->current_scene = SceneAttack; | ||
return; //true; | ||
} else { | ||
//error no file name | ||
context->current_scene = SceneAttack; | ||
return; //true; | ||
} | ||
} | ||
|
||
void subbrute_scene_save_name_text_input_callback(void* context) { | ||
furi_assert(context); | ||
SubBruteState* statee = context; | ||
custom_callback(statee); | ||
} | ||
|
||
void subbrute_scene_save_name_on_tick(SubBruteState* context) { | ||
if(backpressed) { | ||
void* validator_context = text_input_get_validator_callback_context(context->text_input); | ||
text_input_set_validator(context->text_input, NULL, NULL); | ||
validator_is_file_free(validator_context); | ||
|
||
// Clear view | ||
text_input_reset(context->text_input); | ||
|
||
// TextInput | ||
view_dispatcher_remove_view(context->view_dispatcher, 0); | ||
text_input_free(context->text_input); | ||
|
||
// Popup | ||
view_dispatcher_remove_view(context->view_dispatcher, 1); | ||
popup_free(context->popup); | ||
|
||
context->current_scene = SceneAttack; | ||
} | ||
} | ||
|
||
bool subbrute_back_event_callback(void* context) { | ||
UNUSED(context); | ||
backpressed = true; | ||
return true; | ||
} | ||
|
||
void subbrute_scene_save_name_on_enter(SubBruteState* context) { | ||
// Text Input | ||
context->text_input = text_input_alloc(); | ||
view_dispatcher_add_view( | ||
context->view_dispatcher, 0, text_input_get_view(context->text_input)); | ||
|
||
// Popup | ||
context->popup = popup_alloc(); | ||
view_dispatcher_add_view(context->view_dispatcher, 1, popup_get_view(context->popup)); | ||
|
||
// Setup view | ||
TextInput* text_input = context->text_input; | ||
bool dev_name_empty = false; | ||
|
||
string_t file_name; | ||
string_t dir_name; | ||
string_init(file_name); | ||
string_init(dir_name); | ||
|
||
if(!subbrute_path_is_file(context->file_path)) { | ||
char file_name_buf[64] = {0}; | ||
set_random_name(file_name_buf, 64); | ||
string_set_str(file_name, file_name_buf); | ||
string_set_str(context->file_path, EXT_PATH("subghz")); | ||
//highlighting the entire filename by default | ||
dev_name_empty = true; | ||
} else { | ||
string_set(context->file_path_tmp, context->file_path); | ||
path_extract_dirname(string_get_cstr(context->file_path), dir_name); | ||
path_extract_filename(context->file_path, file_name, true); | ||
string_set(context->file_path, dir_name); | ||
} | ||
|
||
strncpy(context->file_name_tmp, string_get_cstr(file_name), 64); | ||
text_input_set_header_text(text_input, "Name signal"); | ||
text_input_set_result_callback( | ||
text_input, | ||
subbrute_scene_save_name_text_input_callback, | ||
context, | ||
context->file_name_tmp, | ||
MAX_TEXT_INPUT_LEN, // buffer size | ||
dev_name_empty); | ||
|
||
ValidatorIsFile* validator_is_file = | ||
validator_is_file_alloc_init(string_get_cstr(context->file_path), ".sub", ""); | ||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); | ||
|
||
string_clear(file_name); | ||
string_clear(dir_name); | ||
|
||
view_dispatcher_set_navigation_event_callback( | ||
context->view_dispatcher, subbrute_back_event_callback); | ||
|
||
view_dispatcher_switch_to_view(context->view_dispatcher, 0); | ||
} | ||
|
||
void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context) { | ||
UNUSED(context); | ||
if(event.evt_type == EventTypeKey) { | ||
if(event.input_type == InputTypeShort) { | ||
switch(event.key) { | ||
case InputKeyDown: | ||
case InputKeyUp: | ||
case InputKeyLeft: | ||
case InputKeyRight: | ||
case InputKeyOk: | ||
break; | ||
case InputKeyBack: | ||
//context->current_scene = SceneAttack; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
void subbrute_scene_save_name_on_exit(SubBruteState* context) { | ||
if(!backpressed) { | ||
// Clear validator | ||
void* validator_context = text_input_get_validator_callback_context(context->text_input); | ||
text_input_set_validator(context->text_input, NULL, NULL); | ||
validator_is_file_free(validator_context); | ||
|
||
// Clear view | ||
text_input_reset(context->text_input); | ||
|
||
// Setup view | ||
Popup* popup = context->popup; | ||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); | ||
popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); | ||
popup_set_timeout(popup, 1500); | ||
popup_set_context(popup, context); | ||
popup_set_callback(popup, NULL); | ||
popup_enable_timeout(popup); | ||
view_dispatcher_switch_to_view(context->view_dispatcher, 1); | ||
|
||
furi_delay_ms(1050); | ||
// Clear view | ||
//Popup* popup = subghz->popup; | ||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||
popup_set_icon(popup, 0, 0, NULL); | ||
popup_set_callback(popup, NULL); | ||
popup_set_context(popup, NULL); | ||
popup_set_timeout(popup, 0); | ||
popup_disable_timeout(popup); | ||
|
||
// TextInput | ||
view_dispatcher_remove_view(context->view_dispatcher, 0); | ||
text_input_free(context->text_input); | ||
|
||
// Popup | ||
view_dispatcher_remove_view(context->view_dispatcher, 1); | ||
popup_free(context->popup); | ||
} else { | ||
backpressed = false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "../subbrute.h" | ||
|
||
void subbrute_scene_save_name_on_enter(SubBruteState* context); | ||
void subbrute_scene_save_name_on_exit(SubBruteState* context); | ||
void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context); | ||
void subbrute_scene_save_name_on_tick(SubBruteState* context); |
121 changes: 121 additions & 0 deletions
121
applications/subbrute/scene/subbrute_scene_select_field.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#include "subbrute_scene_select_field.h" | ||
|
||
void center_displayed_key(SubBruteState* context, uint8_t index) { | ||
const char* key_cstr = string_get_cstr(context->key); | ||
uint8_t str_index = (index * 3); | ||
|
||
char display_menu[17] = { | ||
'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'}; | ||
|
||
if(index > 1) { | ||
display_menu[0] = key_cstr[str_index - 6]; | ||
display_menu[1] = key_cstr[str_index - 5]; | ||
} else { | ||
display_menu[0] = ' '; | ||
display_menu[1] = ' '; | ||
} | ||
|
||
if(index > 0) { | ||
display_menu[3] = key_cstr[str_index - 3]; | ||
display_menu[4] = key_cstr[str_index - 2]; | ||
} else { | ||
display_menu[3] = ' '; | ||
display_menu[4] = ' '; | ||
} | ||
|
||
display_menu[7] = key_cstr[str_index]; | ||
display_menu[8] = key_cstr[str_index + 1]; | ||
|
||
if((str_index + 4) <= (uint8_t)strlen(key_cstr)) { | ||
display_menu[11] = key_cstr[str_index + 3]; | ||
display_menu[12] = key_cstr[str_index + 4]; | ||
} else { | ||
display_menu[11] = ' '; | ||
display_menu[12] = ' '; | ||
} | ||
|
||
if((str_index + 8) <= (uint8_t)strlen(key_cstr)) { | ||
display_menu[14] = key_cstr[str_index + 6]; | ||
display_menu[15] = key_cstr[str_index + 7]; | ||
} else { | ||
display_menu[14] = ' '; | ||
display_menu[15] = ' '; | ||
} | ||
|
||
string_reset(context->notification_msg); | ||
string_set_str(context->notification_msg, display_menu); | ||
} | ||
|
||
void subbrute_scene_select_field_on_enter(SubBruteState* context) { | ||
string_clear(context->notification_msg); | ||
} | ||
|
||
void subbrute_scene_select_field_on_exit(SubBruteState* context) { | ||
UNUSED(context); | ||
} | ||
|
||
void subbrute_scene_select_field_on_tick(SubBruteState* context) { | ||
UNUSED(context); | ||
} | ||
|
||
void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context) { | ||
if(event.evt_type == EventTypeKey) { | ||
if(event.input_type == InputTypeShort) { | ||
//const char* key_cstr = string_get_cstr(context->key); | ||
|
||
// don't look, it's ugly but I'm a python dev so... | ||
/*uint8_t nb_bytes = 0; | ||
for(uint8_t i = 0; i < strlen(key_cstr); i++) { | ||
if(' ' == key_cstr[i]) { | ||
nb_bytes++; | ||
} | ||
}*/ | ||
|
||
switch(event.key) { | ||
case InputKeyDown: | ||
case InputKeyUp: | ||
break; | ||
case InputKeyLeft: | ||
if(context->key_index > 0) { | ||
context->key_index--; | ||
} | ||
break; | ||
case InputKeyRight: | ||
if(context->key_index < 7) { | ||
context->key_index++; | ||
} | ||
break; | ||
case InputKeyOk: | ||
string_reset(context->notification_msg); | ||
context->current_scene = SceneAttack; | ||
break; | ||
case InputKeyBack: | ||
string_reset(context->notification_msg); | ||
context->current_scene = SceneSelectFile; | ||
break; | ||
} | ||
//FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes); | ||
} | ||
} | ||
} | ||
|
||
void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context) { | ||
canvas_clear(canvas); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Frame | ||
//canvas_draw_frame(canvas, 0, 0, 128, 64); | ||
|
||
// Title | ||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "use < > to select field"); | ||
|
||
char msg_index[18]; | ||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index); | ||
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index); | ||
|
||
center_displayed_key(context, context->key_index); | ||
canvas_set_font(canvas, FontSecondary); | ||
canvas_draw_str_aligned( | ||
canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#include "../subbrute.h" | ||
|
||
void subbrute_scene_select_field_on_enter(SubBruteState* context); | ||
void subbrute_scene_select_field_on_exit(SubBruteState* context); | ||
void subbrute_scene_select_field_on_tick(SubBruteState* context); | ||
void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context); | ||
void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context); | ||
void center_displayed_key(SubBruteState* context, uint8_t index); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
#include "subbrute.h" | ||
|
||
#include "scene/subbrute_scene_load_file.h" | ||
#include "scene/subbrute_scene_select_field.h" | ||
#include "scene/subbrute_scene_run_attack.h" | ||
#include "scene/subbrute_scene_entrypoint.h" | ||
#include "scene/subbrute_scene_save_name.h" | ||
|
||
static void draw_callback(Canvas* const canvas, void* ctx) { | ||
SubBruteState* subbrute_state = (SubBruteState*)acquire_mutex((ValueMutex*)ctx, 100); | ||
|
||
if(subbrute_state == NULL) { | ||
return; | ||
} | ||
|
||
// Draw correct Canvas | ||
switch(subbrute_state->current_scene) { | ||
case NoneScene: | ||
case SceneSelectFile: | ||
subbrute_scene_load_file_on_draw(canvas, subbrute_state); | ||
break; | ||
case SceneSelectField: | ||
subbrute_scene_select_field_on_draw(canvas, subbrute_state); | ||
break; | ||
case SceneAttack: | ||
subbrute_scene_run_attack_on_draw(canvas, subbrute_state); | ||
break; | ||
case SceneEntryPoint: | ||
subbrute_scene_entrypoint_on_draw(canvas, subbrute_state); | ||
break; | ||
case SceneSaveName: | ||
break; | ||
} | ||
|
||
release_mutex((ValueMutex*)ctx, subbrute_state); | ||
} | ||
|
||
void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { | ||
furi_assert(event_queue); | ||
|
||
SubBruteEvent event = { | ||
.evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type}; | ||
furi_message_queue_put(event_queue, &event, 100); | ||
} | ||
|
||
static void timer_callback(FuriMessageQueue* event_queue) { | ||
furi_assert(event_queue); | ||
SubBruteEvent event = { | ||
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease}; | ||
furi_message_queue_put(event_queue, &event, 100); | ||
} | ||
|
||
SubBruteState* subbrute_alloc() { | ||
SubBruteState* subbrute = malloc(sizeof(SubBruteState)); | ||
|
||
string_init(subbrute->protocol); | ||
string_init(subbrute->preset); | ||
string_init(subbrute->file_path); | ||
string_init(subbrute->file_path_tmp); | ||
string_init_set(subbrute->notification_msg, ""); | ||
string_init(subbrute->candidate); | ||
string_init(subbrute->flipper_format_string); | ||
|
||
subbrute->previous_scene = NoneScene; | ||
subbrute->current_scene = SceneSelectFile; | ||
subbrute->is_running = true; | ||
subbrute->is_attacking = false; | ||
subbrute->key_index = 7; | ||
subbrute->notify = furi_record_open(RECORD_NOTIFICATION); | ||
|
||
subbrute->view_dispatcher = view_dispatcher_alloc(); | ||
|
||
//Dialog | ||
subbrute->dialogs = furi_record_open(RECORD_DIALOGS); | ||
|
||
subbrute->preset_def = malloc(sizeof(SubGhzPresetDefinition)); | ||
|
||
subbrute->flipper_format = flipper_format_string_alloc(); | ||
subbrute->environment = subghz_environment_alloc(); | ||
subbrute->receiver = subghz_receiver_alloc_init(subbrute->environment); | ||
subghz_receiver_set_filter(subbrute->receiver, SubGhzProtocolFlag_Decodable); | ||
|
||
return subbrute; | ||
} | ||
|
||
void subbrute_free(SubBruteState* subbrute) { | ||
//Dialog | ||
furi_record_close(RECORD_DIALOGS); | ||
|
||
notification_message(subbrute->notify, &sequence_blink_stop); | ||
|
||
furi_record_close(RECORD_NOTIFICATION); | ||
|
||
view_dispatcher_free(subbrute->view_dispatcher); | ||
|
||
string_clear(subbrute->preset); | ||
string_clear(subbrute->candidate); | ||
|
||
// Path strings | ||
string_clear(subbrute->file_path); | ||
string_clear(subbrute->file_path_tmp); | ||
string_clear(subbrute->notification_msg); | ||
string_clear(subbrute->candidate); | ||
string_clear(subbrute->flipper_format_string); | ||
|
||
flipper_format_free(subbrute->flipper_format); | ||
subghz_environment_free(subbrute->environment); | ||
subghz_receiver_free(subbrute->receiver); | ||
|
||
free(subbrute->preset_def); | ||
|
||
// The rest | ||
free(subbrute); | ||
} | ||
|
||
// ENTRYPOINT | ||
int32_t subbrute_start(void* p) { | ||
UNUSED(p); | ||
// Input | ||
FURI_LOG_I(TAG, "Initializing input"); | ||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SubBruteEvent)); | ||
SubBruteState* subbrute_state = subbrute_alloc(); | ||
ValueMutex subbrute_state_mutex; | ||
|
||
// Mutex | ||
FURI_LOG_I(TAG, "Initializing flipfrid mutex"); | ||
if(!init_mutex(&subbrute_state_mutex, subbrute_state, sizeof(SubBruteState))) { | ||
FURI_LOG_E(TAG, "cannot create mutex\r\n"); | ||
furi_message_queue_free(event_queue); | ||
subbrute_free(subbrute_state); | ||
return 255; | ||
} | ||
|
||
furi_hal_power_suppress_charge_enter(); | ||
|
||
// Configure view port | ||
FURI_LOG_I(TAG, "Initializing viewport"); | ||
ViewPort* view_port = view_port_alloc(); | ||
view_port_draw_callback_set(view_port, draw_callback, &subbrute_state_mutex); | ||
view_port_input_callback_set(view_port, input_callback, event_queue); | ||
|
||
// Configure timer | ||
FURI_LOG_I(TAG, "Initializing timer"); | ||
FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue); | ||
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second | ||
|
||
// Register view port in GUI | ||
FURI_LOG_I(TAG, "Initializing gui"); | ||
subbrute_state->gui = furi_record_open(RECORD_GUI); | ||
gui_add_view_port(subbrute_state->gui, view_port, GuiLayerFullscreen); | ||
|
||
view_dispatcher_attach_to_gui( | ||
subbrute_state->view_dispatcher, subbrute_state->gui, ViewDispatcherTypeFullscreen); | ||
|
||
subbrute_state->current_scene = SceneEntryPoint; | ||
|
||
// Init values | ||
SubBruteEvent event; | ||
while(subbrute_state->is_running) { | ||
// Get next event | ||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25); | ||
if(event_status == FuriStatusOk) { | ||
if(event.evt_type == EventTypeKey) { | ||
//Handle event key | ||
FURI_LOG_D(TAG, "EVENT ###"); | ||
switch(subbrute_state->current_scene) { | ||
case SceneSelectFile: | ||
subbrute_scene_load_file_on_event(event, subbrute_state); | ||
break; | ||
case SceneSelectField: | ||
subbrute_scene_select_field_on_event(event, subbrute_state); | ||
break; | ||
case SceneSaveName: | ||
subbrute_scene_save_name_on_event(event, subbrute_state); | ||
break; | ||
case SceneAttack: | ||
subbrute_scene_run_attack_on_event(event, subbrute_state); | ||
break; | ||
case NoneScene: | ||
case SceneEntryPoint: | ||
subbrute_scene_entrypoint_on_event(event, subbrute_state); | ||
break; | ||
} | ||
|
||
} else if(event.evt_type == EventTypeTick) { | ||
//Handle event tick | ||
if(subbrute_state->current_scene != subbrute_state->previous_scene) { | ||
// Trigger Exit Scene | ||
switch(subbrute_state->previous_scene) { | ||
case SceneSelectFile: | ||
subbrute_scene_load_file_on_exit(subbrute_state); | ||
break; | ||
case SceneSelectField: | ||
subbrute_scene_select_field_on_exit(subbrute_state); | ||
break; | ||
case SceneAttack: | ||
subbrute_scene_run_attack_on_exit(subbrute_state); | ||
break; | ||
case SceneEntryPoint: | ||
subbrute_scene_entrypoint_on_exit(subbrute_state); | ||
break; | ||
case SceneSaveName: | ||
subbrute_scene_save_name_on_exit(subbrute_state); | ||
break; | ||
case NoneScene: | ||
break; | ||
} | ||
|
||
// Trigger Entry Scene | ||
switch(subbrute_state->current_scene) { | ||
case NoneScene: | ||
case SceneSelectFile: | ||
subbrute_scene_load_file_on_enter(subbrute_state); | ||
break; | ||
case SceneSelectField: | ||
subbrute_scene_select_field_on_enter(subbrute_state); | ||
break; | ||
case SceneAttack: | ||
subbrute_scene_run_attack_on_enter(subbrute_state); | ||
break; | ||
case SceneSaveName: | ||
subbrute_scene_save_name_on_enter(subbrute_state); | ||
break; | ||
case SceneEntryPoint: | ||
subbrute_scene_entrypoint_on_enter(subbrute_state); | ||
break; | ||
} | ||
subbrute_state->previous_scene = subbrute_state->current_scene; | ||
} | ||
|
||
// Trigger Tick Scene | ||
switch(subbrute_state->current_scene) { | ||
case NoneScene: | ||
case SceneSelectFile: | ||
subbrute_scene_load_file_on_tick(subbrute_state); | ||
break; | ||
case SceneSelectField: | ||
subbrute_scene_select_field_on_tick(subbrute_state); | ||
break; | ||
case SceneAttack: | ||
subbrute_scene_run_attack_on_tick(subbrute_state); | ||
break; | ||
case SceneEntryPoint: | ||
subbrute_scene_entrypoint_on_tick(subbrute_state); | ||
break; | ||
case SceneSaveName: | ||
subbrute_scene_save_name_on_tick(subbrute_state); | ||
break; | ||
} | ||
view_port_update(view_port); | ||
} | ||
} | ||
} | ||
|
||
// Cleanup | ||
furi_timer_stop(timer); | ||
furi_timer_free(timer); | ||
|
||
furi_hal_power_suppress_charge_exit(); | ||
|
||
FURI_LOG_I(TAG, "Cleaning up"); | ||
gui_remove_view_port(subbrute_state->gui, view_port); | ||
view_port_free(view_port); | ||
furi_message_queue_free(event_queue); | ||
furi_record_close(RECORD_GUI); | ||
subbrute_free(subbrute_state); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#pragma once | ||
#include <furi.h> | ||
#include <furi_hal.h> | ||
#include <input/input.h> | ||
#include <gui/gui.h> | ||
#include "m-string.h" | ||
|
||
#include <toolbox/stream/stream.h> | ||
#include <lib/subghz/transmitter.h> | ||
#include <lib/subghz/receiver.h> | ||
#include <flipper_format/flipper_format_i.h> | ||
#include <dialogs/dialogs.h> | ||
#include <notification/notification.h> | ||
#include <notification/notification_messages.h> | ||
#include <gui/view_dispatcher.h> | ||
#include <gui/modules/text_input.h> | ||
#include <gui/modules/popup.h> | ||
|
||
#define TAG "SUBBRUTE" | ||
|
||
typedef enum { | ||
NoneScene, | ||
SceneSelectFile, | ||
SceneSelectField, | ||
SceneAttack, | ||
SceneEntryPoint, | ||
SceneSaveName | ||
} SubBruteScene; | ||
|
||
typedef enum { | ||
SubBruteAttackLoadFile, | ||
SubBruteAttackCAME12bit433, | ||
SubBruteAttackCAME12bit868, | ||
SubBruteAttackChamberlain9bit315, | ||
SubBruteAttackChamberlain9bit390, | ||
SubBruteAttackLinear10bit300, | ||
SubBruteAttackLinear10bit310, | ||
SubBruteAttackNICE12bit433, | ||
SubBruteAttackNICE12bit868, | ||
} SubBruteAttacks; | ||
|
||
typedef enum { | ||
EventTypeTick, | ||
EventTypeKey, | ||
EventTypeCustom, | ||
} EventType; | ||
|
||
typedef struct { | ||
EventType evt_type; | ||
InputKey key; | ||
InputType input_type; | ||
} SubBruteEvent; | ||
|
||
// STRUCTS | ||
typedef struct { | ||
// Application stuff | ||
bool is_running; | ||
bool is_attacking; | ||
SubBruteScene current_scene; | ||
SubBruteScene previous_scene; | ||
NotificationApp* notify; | ||
Gui* gui; | ||
ViewDispatcher* view_dispatcher; | ||
TextInput* text_input; | ||
Popup* popup; | ||
|
||
// SubGhz Stuff | ||
FlipperFormat* flipper_format; | ||
SubGhzEnvironment* environment; | ||
SubGhzTransmitter* transmitter; | ||
SubGhzReceiver* receiver; | ||
SubGhzProtocolDecoderBase* decoder_result; | ||
SubGhzPresetDefinition* preset_def; | ||
string_t preset; | ||
Stream* stream; | ||
string_t protocol; | ||
uint32_t frequency; | ||
uint32_t repeat; | ||
uint32_t bit; | ||
string_t key; | ||
uint32_t te; | ||
|
||
// Context Stuff | ||
DialogsApp* dialogs; | ||
char file_name_tmp[64]; | ||
string_t file_path; | ||
string_t file_path_tmp; | ||
string_t notification_msg; | ||
uint8_t key_index; | ||
uint64_t payload; | ||
string_t candidate; | ||
uint8_t str_index; | ||
string_t flipper_format_string; | ||
|
||
SubBruteAttacks attack; | ||
|
||
//Menu stuff | ||
uint8_t menu_index; | ||
|
||
// RAW stuff | ||
string_t subbrute_raw_one; | ||
string_t subbrute_raw_zero; | ||
string_t subbrute_raw_stop; | ||
|
||
} SubBruteState; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "subbrute_utils.h" | ||
|
||
bool subbrute_is_frequency_allowed(SubBruteState* context) { | ||
// I know you don't like it but laws are laws | ||
// It's opensource so do whatever you want, but remember the risks :) | ||
// (Yes, this comment is the only purpose of this function) | ||
bool r = furi_hal_subghz_is_tx_allowed(context->frequency); | ||
if(!r) { | ||
FURI_LOG_E(TAG, "Frequency %d is not allowed in your region", context->frequency); | ||
notification_message(context->notify, &sequence_single_vibro); | ||
} | ||
return r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#pragma once | ||
#include "subbrute.h" | ||
|
||
bool subbrute_is_frequency_allowed(SubBruteState* context); |