Merge pull request #507 from gid9798/Fuzzer
New RFID(125) and iButton Fuzzers
@@ -134,7 +134,8 @@ You can support us by using links or addresses below:
|
||||
|
||||
### Community apps included:
|
||||
|
||||
- **RFID Fuzzer** [(by Ganapati & @xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/54) & New protocols by @mvanzanten
|
||||
- **RFID Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/unleashed-firmware/pull/507) (original by Ganapati & xMasterX)
|
||||
- **iButton Fuzzer** [(by @gid9798)](https://github.com/DarkFlippers/unleashed-firmware/pull/507) (original by xMasterX)
|
||||
- **Sub-GHz bruteforcer** [(by @derskythe & xMasterX)](https://github.com/derskythe/flipperzero-subbrute) [(original by Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57)
|
||||
- **Sub-GHz playlist** [(by darmiel)](https://github.com/DarkFlippers/unleashed-firmware/pull/62)
|
||||
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
|
||||
@@ -157,7 +158,6 @@ You can support us by using links or addresses below:
|
||||
- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP)
|
||||
- **Unitemp - Temperature sensors reader** (DHT11/22, DS18B20, BMP280, HTU21x and more) [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero)
|
||||
- BH1750 - Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
||||
- **iButton Fuzzer** [(by xMasterX)](https://github.com/xMasterX/ibutton-fuzzer)
|
||||
- HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer)
|
||||
- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager)
|
||||
- Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)
|
||||
|
||||
8
applications/external/flipfrid/LICENSE.md
vendored
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "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.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
36
applications/external/flipfrid/README.md
vendored
@@ -1,36 +0,0 @@
|
||||
# Flipfrid
|
||||
|
||||
Basic LFRFID Fuzzer.
|
||||
|
||||
## Why
|
||||
|
||||
Flipfrid is a simple Rfid fuzzer using lfrfid protocols (125khz).
|
||||
Objective is to provide a simple to use fuzzer to test readers by emulating various cards.
|
||||
|
||||
- EM4100 cards use a 1 byte customer id and 4 bytes card id.
|
||||
- HIDProx cards use a 2 byte customer id and 3 byte card id.
|
||||
|
||||
## How
|
||||
|
||||
1) Select the Protocol with the left and right arrows
|
||||
2) Select the Mode with the up and down arrows
|
||||
3) Set TD (Time delay) between ID switch if you need, or left it as is
|
||||
4) Click Start
|
||||
|
||||
### Info
|
||||
|
||||
There are 4 Protocols:
|
||||
- EM4100
|
||||
- HIDProx
|
||||
- PAC/Stanley
|
||||
- H10301
|
||||
|
||||
There are 4 modes:
|
||||
- Default Values: Try factory/default keys and emulate one after the other.
|
||||
- BF customer id: An iteration from 0X00 to 0XFF on the first byte.
|
||||
- Load Dump file: Load an existing dump (.rfid) generated by Flipperzero, select an index and bruteforce from 0X00 to 0XFF;
|
||||
- Uids list: Iterate over an input text file (one uid per line) and emulate one after the other.
|
||||
|
||||
|
||||
TODO :
|
||||
- Add second byte test to `BF customer id`
|
||||
12
applications/external/flipfrid/application.fam
vendored
@@ -1,12 +0,0 @@
|
||||
App(
|
||||
appid="rfid_fuzzer",
|
||||
name="RFID Fuzzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="flipfrid_start",
|
||||
requires=["gui", "storage", "dialogs", "input", "notification"],
|
||||
stack_size=2 * 1024,
|
||||
order=15,
|
||||
fap_icon="rfid_10px.png",
|
||||
fap_category="Tools",
|
||||
fap_icon_assets="images",
|
||||
)
|
||||
276
applications/external/flipfrid/flipfrid.c
vendored
@@ -1,276 +0,0 @@
|
||||
#include "flipfrid.h"
|
||||
|
||||
#include "scene/flipfrid_scene_entrypoint.h"
|
||||
#include "scene/flipfrid_scene_load_file.h"
|
||||
#include "scene/flipfrid_scene_select_field.h"
|
||||
#include "scene/flipfrid_scene_run_attack.h"
|
||||
#include "scene/flipfrid_scene_load_custom_uids.h"
|
||||
|
||||
#define RFIDFUZZER_APP_FOLDER "/ext/rfidfuzzer"
|
||||
|
||||
static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
FlipFridState* flipfrid_state = ctx;
|
||||
furi_mutex_acquire(flipfrid_state->mutex, FuriWaitForever);
|
||||
|
||||
// Draw correct Canvas
|
||||
switch(flipfrid_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
flipfrid_scene_entrypoint_on_draw(canvas, flipfrid_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
flipfrid_scene_load_file_on_draw(canvas, flipfrid_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
flipfrid_scene_select_field_on_draw(canvas, flipfrid_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
flipfrid_scene_run_attack_on_draw(canvas, flipfrid_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
flipfrid_scene_load_custom_uids_on_draw(canvas, flipfrid_state);
|
||||
break;
|
||||
}
|
||||
|
||||
furi_mutex_release(flipfrid_state->mutex);
|
||||
}
|
||||
|
||||
void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
FlipFridEvent event = {
|
||||
.evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
static void flipfrid_timer_callback(FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
FlipFridEvent event = {
|
||||
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
FlipFridState* flipfrid_alloc() {
|
||||
FlipFridState* flipfrid = malloc(sizeof(FlipFridState));
|
||||
flipfrid->notification_msg = furi_string_alloc();
|
||||
flipfrid->attack_name = furi_string_alloc();
|
||||
flipfrid->proto_name = furi_string_alloc();
|
||||
flipfrid->data_str = furi_string_alloc();
|
||||
|
||||
flipfrid->main_menu_items[0] = furi_string_alloc_set("Default Values");
|
||||
flipfrid->main_menu_items[1] = furi_string_alloc_set("BF Customer ID");
|
||||
flipfrid->main_menu_items[2] = furi_string_alloc_set("Load File");
|
||||
flipfrid->main_menu_items[3] = furi_string_alloc_set("Load UIDs from file");
|
||||
|
||||
flipfrid->main_menu_proto_items[0] = furi_string_alloc_set("EM4100");
|
||||
flipfrid->main_menu_proto_items[1] = furi_string_alloc_set("HIDProx");
|
||||
flipfrid->main_menu_proto_items[2] = furi_string_alloc_set("PAC/Stanley");
|
||||
flipfrid->main_menu_proto_items[3] = furi_string_alloc_set("H10301");
|
||||
|
||||
flipfrid->previous_scene = NoneScene;
|
||||
flipfrid->current_scene = SceneEntryPoint;
|
||||
flipfrid->is_running = true;
|
||||
flipfrid->is_attacking = false;
|
||||
flipfrid->key_index = 0;
|
||||
flipfrid->menu_index = 0;
|
||||
flipfrid->menu_proto_index = 0;
|
||||
|
||||
flipfrid->attack = FlipFridAttackDefaultValues;
|
||||
flipfrid->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
flipfrid->data[0] = 0x00;
|
||||
flipfrid->data[1] = 0x00;
|
||||
flipfrid->data[2] = 0x00;
|
||||
flipfrid->data[3] = 0x00;
|
||||
flipfrid->data[4] = 0x00;
|
||||
flipfrid->data[5] = 0x00;
|
||||
|
||||
flipfrid->payload[0] = 0x00;
|
||||
flipfrid->payload[1] = 0x00;
|
||||
flipfrid->payload[2] = 0x00;
|
||||
flipfrid->payload[3] = 0x00;
|
||||
flipfrid->payload[4] = 0x00;
|
||||
flipfrid->payload[5] = 0x00;
|
||||
|
||||
//Dialog
|
||||
flipfrid->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
return flipfrid;
|
||||
}
|
||||
|
||||
void flipfrid_free(FlipFridState* flipfrid) {
|
||||
//Dialog
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
notification_message(flipfrid->notify, &sequence_blink_stop);
|
||||
|
||||
// Strings
|
||||
furi_string_free(flipfrid->notification_msg);
|
||||
furi_string_free(flipfrid->attack_name);
|
||||
furi_string_free(flipfrid->proto_name);
|
||||
furi_string_free(flipfrid->data_str);
|
||||
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
furi_string_free(flipfrid->main_menu_items[i]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < 4; i++) {
|
||||
furi_string_free(flipfrid->main_menu_proto_items[i]);
|
||||
}
|
||||
|
||||
// The rest
|
||||
free(flipfrid);
|
||||
}
|
||||
|
||||
// ENTRYPOINT
|
||||
int32_t flipfrid_start(void* p) {
|
||||
UNUSED(p);
|
||||
// Input
|
||||
FURI_LOG_I(TAG, "Initializing input");
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
|
||||
FlipFridState* flipfrid_state = flipfrid_alloc();
|
||||
|
||||
flipfrid_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
if(!flipfrid_state->mutex) {
|
||||
FURI_LOG_E(TAG, "cannot create mutex\r\n");
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
flipfrid_free(flipfrid_state);
|
||||
return 255;
|
||||
}
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(!storage_simply_mkdir(storage, RFIDFUZZER_APP_FOLDER)) {
|
||||
FURI_LOG_E(TAG, "Could not create folder %s", RFIDFUZZER_APP_FOLDER);
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
// Configure view port
|
||||
FURI_LOG_I(TAG, "Initializing viewport");
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, flipfrid_draw_callback, flipfrid_state);
|
||||
view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue);
|
||||
|
||||
// Configure timer
|
||||
FURI_LOG_I(TAG, "Initializing timer");
|
||||
FuriTimer* timer =
|
||||
furi_timer_alloc(flipfrid_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");
|
||||
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
// Init values
|
||||
FlipFridEvent event;
|
||||
while(flipfrid_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
|
||||
switch(flipfrid_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
flipfrid_scene_entrypoint_on_event(event, flipfrid_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
flipfrid_scene_load_file_on_event(event, flipfrid_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
flipfrid_scene_select_field_on_event(event, flipfrid_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
flipfrid_scene_run_attack_on_event(event, flipfrid_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
flipfrid_scene_load_custom_uids_on_event(event, flipfrid_state);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if(event.evt_type == EventTypeTick) {
|
||||
//Handle event tick
|
||||
if(flipfrid_state->current_scene != flipfrid_state->previous_scene) {
|
||||
// Trigger Exit Scene
|
||||
switch(flipfrid_state->previous_scene) {
|
||||
case SceneEntryPoint:
|
||||
flipfrid_scene_entrypoint_on_exit(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
flipfrid_scene_load_file_on_exit(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
flipfrid_scene_select_field_on_exit(flipfrid_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
flipfrid_scene_run_attack_on_exit(flipfrid_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
flipfrid_scene_load_custom_uids_on_exit(flipfrid_state);
|
||||
break;
|
||||
case NoneScene:
|
||||
break;
|
||||
}
|
||||
|
||||
// Trigger Entry Scene
|
||||
switch(flipfrid_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
flipfrid_scene_entrypoint_on_enter(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
flipfrid_scene_load_file_on_enter(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
flipfrid_scene_select_field_on_enter(flipfrid_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
flipfrid_scene_run_attack_on_enter(flipfrid_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
flipfrid_scene_load_custom_uids_on_enter(flipfrid_state);
|
||||
break;
|
||||
}
|
||||
flipfrid_state->previous_scene = flipfrid_state->current_scene;
|
||||
}
|
||||
|
||||
// Trigger Tick Scene
|
||||
switch(flipfrid_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
flipfrid_scene_entrypoint_on_tick(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
flipfrid_scene_load_file_on_tick(flipfrid_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
flipfrid_scene_select_field_on_tick(flipfrid_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
flipfrid_scene_run_attack_on_tick(flipfrid_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
flipfrid_scene_load_custom_uids_on_tick(flipfrid_state);
|
||||
break;
|
||||
}
|
||||
view_port_update(view_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
furi_timer_stop(timer);
|
||||
furi_timer_free(timer);
|
||||
|
||||
FURI_LOG_I(TAG, "Cleaning up");
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_mutex_free(flipfrid_state->mutex);
|
||||
flipfrid_free(flipfrid_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
94
applications/external/flipfrid/flipfrid.h
vendored
@@ -1,94 +0,0 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <toolbox/stream/string_stream.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
|
||||
#include <rfid_fuzzer_icons.h>
|
||||
|
||||
#include <lib/lfrfid/lfrfid_worker.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
|
||||
#define TAG "FlipFrid"
|
||||
|
||||
typedef enum {
|
||||
FlipFridAttackDefaultValues,
|
||||
FlipFridAttackBfCustomerId,
|
||||
FlipFridAttackLoadFile,
|
||||
FlipFridAttackLoadFileCustomUids,
|
||||
} FlipFridAttacks;
|
||||
|
||||
typedef enum {
|
||||
EM4100,
|
||||
HIDProx,
|
||||
PAC,
|
||||
H10301,
|
||||
} FlipFridProtos;
|
||||
|
||||
typedef enum {
|
||||
NoneScene,
|
||||
SceneEntryPoint,
|
||||
SceneSelectFile,
|
||||
SceneSelectField,
|
||||
SceneAttack,
|
||||
SceneLoadCustomUids,
|
||||
} FlipFridScene;
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
EventType evt_type;
|
||||
InputKey key;
|
||||
InputType input_type;
|
||||
} FlipFridEvent;
|
||||
|
||||
// STRUCTS
|
||||
typedef struct {
|
||||
FuriMutex* mutex;
|
||||
bool is_running;
|
||||
bool is_attacking;
|
||||
FlipFridScene current_scene;
|
||||
FlipFridScene previous_scene;
|
||||
NotificationApp* notify;
|
||||
u_int8_t menu_index;
|
||||
u_int8_t menu_proto_index;
|
||||
|
||||
FuriString* data_str;
|
||||
uint8_t data[6];
|
||||
uint8_t payload[6];
|
||||
uint8_t attack_step;
|
||||
FlipFridAttacks attack;
|
||||
FlipFridProtos proto;
|
||||
FuriString* attack_name;
|
||||
FuriString* proto_name;
|
||||
FuriString* main_menu_items[4];
|
||||
FuriString* main_menu_proto_items[4];
|
||||
|
||||
DialogsApp* dialogs;
|
||||
FuriString* notification_msg;
|
||||
uint8_t key_index;
|
||||
LFRFIDWorker* worker;
|
||||
ProtocolDict* dict;
|
||||
ProtocolId protocol;
|
||||
bool workr_rund;
|
||||
bool attack_stop_called;
|
||||
|
||||
uint8_t time_between_cards;
|
||||
|
||||
// Used for custom dictionnary
|
||||
Stream* uids_stream;
|
||||
} FlipFridState;
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "flipfrid_scene_entrypoint.h"
|
||||
|
||||
void flipfrid_scene_entrypoint_menu_callback(
|
||||
FlipFridState* context,
|
||||
uint32_t index,
|
||||
uint32_t proto_index) {
|
||||
switch(index) {
|
||||
case FlipFridAttackDefaultValues:
|
||||
context->attack = FlipFridAttackDefaultValues;
|
||||
context->current_scene = SceneAttack;
|
||||
furi_string_set(context->attack_name, "Default Values");
|
||||
break;
|
||||
case FlipFridAttackBfCustomerId:
|
||||
context->attack = FlipFridAttackBfCustomerId;
|
||||
context->current_scene = SceneAttack;
|
||||
furi_string_set(context->attack_name, "Bad Customer ID");
|
||||
break;
|
||||
case FlipFridAttackLoadFile:
|
||||
context->attack = FlipFridAttackLoadFile;
|
||||
context->current_scene = SceneSelectFile;
|
||||
furi_string_set(context->attack_name, "Load File");
|
||||
break;
|
||||
case FlipFridAttackLoadFileCustomUids:
|
||||
context->attack = FlipFridAttackLoadFileCustomUids;
|
||||
context->current_scene = SceneLoadCustomUids;
|
||||
furi_string_set(context->attack_name, "Load Custom UIDs");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(proto_index) {
|
||||
case EM4100:
|
||||
context->proto = EM4100;
|
||||
furi_string_set(context->proto_name, "EM4100");
|
||||
break;
|
||||
case HIDProx:
|
||||
context->proto = HIDProx;
|
||||
furi_string_set(context->proto_name, "HIDProx");
|
||||
break;
|
||||
case PAC:
|
||||
context->proto = PAC;
|
||||
furi_string_set(context->proto_name, "PAC/Stanley");
|
||||
break;
|
||||
case H10301:
|
||||
context->proto = H10301;
|
||||
furi_string_set(context->proto_name, "H10301");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
|
||||
// Clear the previous payload
|
||||
context->payload[0] = 0x00;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
context->payload[5] = 0x00;
|
||||
|
||||
context->menu_index = 0;
|
||||
/*for(uint32_t i = 0; i < 4; i++) {
|
||||
menu_items[i] = furi_string_alloc();
|
||||
}*/
|
||||
|
||||
context->menu_proto_index = 0;
|
||||
/*for(uint32_t i = 0; i < 4; i++) {
|
||||
menu_proto_items[i] = furi_string_alloc();
|
||||
}*/
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_tick(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
if(context->menu_index < FlipFridAttackLoadFileCustomUids) {
|
||||
context->menu_index++;
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
if(context->menu_index > FlipFridAttackDefaultValues) {
|
||||
context->menu_index--;
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->menu_proto_index > EM4100) {
|
||||
context->menu_proto_index--;
|
||||
} else if(context->menu_proto_index == EM4100) {
|
||||
context->menu_proto_index = H10301;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->menu_proto_index < H10301) {
|
||||
context->menu_proto_index++;
|
||||
} else if(context->menu_proto_index == H10301) {
|
||||
context->menu_proto_index = EM4100;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
flipfrid_scene_entrypoint_menu_callback(
|
||||
context, context->menu_index, context->menu_proto_index);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->is_running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(context->main_menu_items != NULL) {
|
||||
if(context->main_menu_items[context->menu_index] != NULL) {
|
||||
if(context->menu_index > FlipFridAttackDefaultValues) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
24,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index - 1]));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
36,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index]));
|
||||
|
||||
if(context->menu_index < FlipFridAttackLoadFileCustomUids) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
48,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index + 1]));
|
||||
}
|
||||
|
||||
if(context->menu_proto_index > EM4100) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(
|
||||
context->main_menu_proto_items[context->menu_proto_index - 1]));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 27, 4, AlignCenter, AlignTop, "<");
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
4,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_proto_items[context->menu_proto_index]));
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 101, 4, AlignCenter, AlignTop, ">");
|
||||
|
||||
if(context->menu_proto_index < H10301) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(
|
||||
context->main_menu_proto_items[context->menu_proto_index + 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "../flipfrid.h"
|
||||
|
||||
void flipfrid_scene_entrypoint_on_enter(FlipFridState* context);
|
||||
void flipfrid_scene_entrypoint_on_exit(FlipFridState* context);
|
||||
void flipfrid_scene_entrypoint_on_tick(FlipFridState* context);
|
||||
void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context);
|
||||
void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context);
|
||||
@@ -1,85 +0,0 @@
|
||||
#include "flipfrid_scene_load_custom_uids.h"
|
||||
#include "flipfrid_scene_run_attack.h"
|
||||
#include "flipfrid_scene_entrypoint.h"
|
||||
|
||||
#define LFRFID_UIDS_EXTENSION ".txt"
|
||||
#define RFIDFUZZER_APP_PATH_FOLDER "/ext/rfidfuzzer"
|
||||
|
||||
bool flipfrid_load_uids(FlipFridState* context, const char* file_path) {
|
||||
bool result = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
context->uids_stream = buffered_file_stream_alloc(storage);
|
||||
result =
|
||||
buffered_file_stream_open(context->uids_stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
// Close if loading fails
|
||||
if(!result) {
|
||||
buffered_file_stream_close(context->uids_stream);
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipfrid_load_custom_uids_from_file(FlipFridState* context) {
|
||||
// Input events and views are managed by file_select
|
||||
FuriString* uid_path;
|
||||
uid_path = furi_string_alloc();
|
||||
furi_string_set(uid_path, RFIDFUZZER_APP_PATH_FOLDER);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, LFRFID_UIDS_EXTENSION, &I_125_10px);
|
||||
browser_options.base_path = RFIDFUZZER_APP_PATH_FOLDER;
|
||||
browser_options.hide_ext = false;
|
||||
|
||||
bool res = dialog_file_browser_show(context->dialogs, uid_path, uid_path, &browser_options);
|
||||
|
||||
if(res) {
|
||||
res = flipfrid_load_uids(context, furi_string_get_cstr(uid_path));
|
||||
}
|
||||
|
||||
furi_string_free(uid_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_enter(FlipFridState* context) {
|
||||
if(flipfrid_load_custom_uids_from_file(context)) {
|
||||
// Force context loading
|
||||
flipfrid_scene_run_attack_on_enter(context);
|
||||
context->current_scene = SceneAttack;
|
||||
} else {
|
||||
flipfrid_scene_entrypoint_on_enter(context);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_exit(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_tick(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
case InputKeyUp:
|
||||
case InputKeyLeft:
|
||||
case InputKeyRight:
|
||||
case InputKeyOk:
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(canvas);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../flipfrid.h"
|
||||
|
||||
void flipfrid_scene_load_custom_uids_on_enter(FlipFridState* context);
|
||||
void flipfrid_scene_load_custom_uids_on_exit(FlipFridState* context);
|
||||
void flipfrid_scene_load_custom_uids_on_tick(FlipFridState* context);
|
||||
void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState* context);
|
||||
void flipfrid_scene_load_custom_uids_on_draw(Canvas* canvas, FlipFridState* context);
|
||||
bool flipfrid_load_custom_uids_from_file(FlipFridState* context);
|
||||
@@ -1,193 +0,0 @@
|
||||
#include "flipfrid_scene_load_file.h"
|
||||
#include "flipfrid_scene_entrypoint.h"
|
||||
|
||||
#define LFRFID_APP_EXTENSION ".rfid"
|
||||
#define LFRFID_APP_PATH_FOLDER "/ext/lfrfid"
|
||||
|
||||
bool flipfrid_load(FlipFridState* context, const char* file_path) {
|
||||
bool result = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Error open file");
|
||||
break;
|
||||
}
|
||||
|
||||
// FileType
|
||||
if(!flipper_format_read_string(fff_data_file, "Filetype", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Filetype");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Filetypes");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Filetype: %s", furi_string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
// Key type
|
||||
if(!flipper_format_read_string(fff_data_file, "Key type", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Key type");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key type: %s", furi_string_get_cstr(temp_str));
|
||||
|
||||
if(context->proto == EM4100) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "EM4100") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == PAC) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "PAC/Stanley") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == H10301) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "H10301") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "HIDProx") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data
|
||||
if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Data");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Key");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", furi_string_get_cstr(context->data_str));
|
||||
|
||||
if(context->proto == EM4100) {
|
||||
if(furi_string_size(context->data_str) != 14) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == PAC) {
|
||||
if(furi_string_size(context->data_str) != 11) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == H10301) {
|
||||
if(furi_string_size(context->data_str) != 8) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(furi_string_size(context->data_str) != 17) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = furi_string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = furi_string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
temp_str2[2] = '\0';
|
||||
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
} while(0);
|
||||
furi_string_free(temp_str);
|
||||
flipper_format_free(fff_data_file);
|
||||
if(result) {
|
||||
FURI_LOG_I(TAG, "Loaded successfully");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Source loaded.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_file_on_enter(FlipFridState* context) {
|
||||
if(flipfrid_load_protocol_from_file(context)) {
|
||||
context->current_scene = SceneSelectField;
|
||||
} else {
|
||||
flipfrid_scene_entrypoint_on_enter(context);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_file_on_exit(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_file_on_tick(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
case InputKeyUp:
|
||||
case InputKeyLeft:
|
||||
case InputKeyRight:
|
||||
case InputKeyOk:
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(canvas);
|
||||
}
|
||||
|
||||
bool flipfrid_load_protocol_from_file(FlipFridState* context) {
|
||||
FuriString* user_file_path;
|
||||
user_file_path = furi_string_alloc();
|
||||
furi_string_set(user_file_path, LFRFID_APP_PATH_FOLDER);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_EXTENSION, &I_125_10px);
|
||||
browser_options.base_path = LFRFID_APP_PATH_FOLDER;
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
bool res = dialog_file_browser_show(
|
||||
context->dialogs, user_file_path, user_file_path, &browser_options);
|
||||
|
||||
if(res) {
|
||||
res = flipfrid_load(context, furi_string_get_cstr(user_file_path));
|
||||
}
|
||||
|
||||
furi_string_free(user_file_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../flipfrid.h"
|
||||
|
||||
void flipfrid_scene_load_file_on_enter(FlipFridState* context);
|
||||
void flipfrid_scene_load_file_on_exit(FlipFridState* context);
|
||||
void flipfrid_scene_load_file_on_tick(FlipFridState* context);
|
||||
void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context);
|
||||
void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context);
|
||||
bool flipfrid_load_protocol_from_file(FlipFridState* context);
|
||||
@@ -1,666 +0,0 @@
|
||||
#include "flipfrid_scene_run_attack.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
uint8_t counter = 0;
|
||||
|
||||
uint8_t id_list[17][5] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_hid[14][6] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, // Incremental UID
|
||||
{0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_pac[17][4] = {
|
||||
{0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
uint8_t id_list_h[14][3] = {
|
||||
{0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56}, // Incremental UID
|
||||
{0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
void flipfrid_scene_run_attack_on_enter(FlipFridState* context) {
|
||||
context->time_between_cards = 10;
|
||||
context->attack_step = 0;
|
||||
context->attack_stop_called = false;
|
||||
context->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
context->worker = lfrfid_worker_alloc(context->dict);
|
||||
if(context->proto == HIDProx) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "HIDProx");
|
||||
} else if(context->proto == PAC) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "PAC/Stanley");
|
||||
} else if(context->proto == H10301) {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "H10301");
|
||||
} else {
|
||||
context->protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_run_attack_on_exit(FlipFridState* context) {
|
||||
if(context->workr_rund) {
|
||||
lfrfid_worker_stop(context->worker);
|
||||
lfrfid_worker_stop_thread(context->worker);
|
||||
context->workr_rund = false;
|
||||
}
|
||||
lfrfid_worker_free(context->worker);
|
||||
protocol_dict_free(context->dict);
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
|
||||
if(context->is_attacking) {
|
||||
if(1 == counter) {
|
||||
protocol_dict_set_data(context->dict, context->protocol, context->payload, 6);
|
||||
lfrfid_worker_free(context->worker);
|
||||
context->worker = lfrfid_worker_alloc(context->dict);
|
||||
lfrfid_worker_start_thread(context->worker);
|
||||
lfrfid_worker_emulate_start(context->worker, context->protocol);
|
||||
context->workr_rund = true;
|
||||
} else if(0 == counter) {
|
||||
if(context->workr_rund) {
|
||||
lfrfid_worker_stop(context->worker);
|
||||
lfrfid_worker_stop_thread(context->worker);
|
||||
context->workr_rund = false;
|
||||
furi_delay_ms(200);
|
||||
}
|
||||
switch(context->attack) {
|
||||
case FlipFridAttackDefaultValues:
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = id_list[context->attack_step][0];
|
||||
context->payload[1] = id_list[context->attack_step][1];
|
||||
context->payload[2] = id_list[context->attack_step][2];
|
||||
context->payload[3] = id_list[context->attack_step][3];
|
||||
context->payload[4] = id_list[context->attack_step][4];
|
||||
|
||||
if(context->attack_step == 16) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = id_list_pac[context->attack_step][0];
|
||||
context->payload[1] = id_list_pac[context->attack_step][1];
|
||||
context->payload[2] = id_list_pac[context->attack_step][2];
|
||||
context->payload[3] = id_list_pac[context->attack_step][3];
|
||||
|
||||
if(context->attack_step == 16) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = id_list_h[context->attack_step][0];
|
||||
context->payload[1] = id_list_h[context->attack_step][1];
|
||||
context->payload[2] = id_list_h[context->attack_step][2];
|
||||
|
||||
if(context->attack_step == 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = id_list_hid[context->attack_step][0];
|
||||
context->payload[1] = id_list_hid[context->attack_step][1];
|
||||
context->payload[2] = id_list_hid[context->attack_step][2];
|
||||
context->payload[3] = id_list_hid[context->attack_step][3];
|
||||
context->payload[4] = id_list_hid[context->attack_step][4];
|
||||
context->payload[5] = id_list_hid[context->attack_step][5];
|
||||
|
||||
if(context->attack_step == 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FlipFridAttackBfCustomerId:
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = context->attack_step;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
context->payload[5] = 0x00;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FlipFridAttackLoadFile:
|
||||
if(context->proto == EM4100) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
context->payload[5] = context->data[5];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FlipFridAttackLoadFileCustomUids:
|
||||
if(context->proto == EM4100) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 11) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(furi_string_size(context->data_str) != 11) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == PAC) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 9) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(furi_string_size(context->data_str) != 9) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == H10301) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 7) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(furi_string_size(context->data_str) != 7) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 3; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 13) break;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(end_of_list) break;
|
||||
if(furi_string_size(context->data_str) != 13) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(counter > context->time_between_cards) {
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards > 5) {
|
||||
context->time_between_cards--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards < 70) {
|
||||
context->time_between_cards++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
counter = 0;
|
||||
if(!context->is_attacking) {
|
||||
notification_message(context->notify, &sequence_blink_start_blue);
|
||||
context->is_attacking = true;
|
||||
} else {
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->is_attacking = false;
|
||||
counter = 0;
|
||||
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
if(context->attack_stop_called) {
|
||||
context->attack_stop_called = false;
|
||||
context->attack_step = 0;
|
||||
if(context->attack == FlipFridAttackLoadFileCustomUids) {
|
||||
furi_string_reset(context->data_str);
|
||||
stream_rewind(context->uids_stream);
|
||||
buffered_file_stream_close(context->uids_stream);
|
||||
}
|
||||
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
|
||||
context->attack_stop_called = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(event.input_type == InputTypeLong) {
|
||||
switch(event.key) {
|
||||
case InputKeyLeft:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards > 0) {
|
||||
if((context->time_between_cards - 10) > 5) {
|
||||
context->time_between_cards -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards < 70) {
|
||||
context->time_between_cards += 10;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* 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, 2, AlignCenter, AlignTop, furi_string_get_cstr(context->attack_name));
|
||||
|
||||
char uid[18];
|
||||
char speed[16];
|
||||
if(context->proto == HIDProx) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4],
|
||||
context->payload[5]);
|
||||
} else if(context->proto == PAC) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3]);
|
||||
} else if(context->proto == H10301) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2]);
|
||||
} else {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4]);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignTop, uid);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 26, AlignCenter, AlignTop, furi_string_get_cstr(context->proto_name));
|
||||
|
||||
snprintf(speed, sizeof(speed), "Time delay: %d", context->time_between_cards);
|
||||
|
||||
//canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Speed:");
|
||||
canvas_draw_str_aligned(canvas, 64, 14, AlignCenter, AlignTop, speed);
|
||||
//char start_stop_msg[20];
|
||||
if(context->is_attacking) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
//snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_left(canvas, "TD -");
|
||||
elements_button_right(canvas, "+ TD");
|
||||
}
|
||||
//canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "../flipfrid.h"
|
||||
|
||||
void flipfrid_scene_run_attack_on_enter(FlipFridState* context);
|
||||
void flipfrid_scene_run_attack_on_exit(FlipFridState* context);
|
||||
void flipfrid_scene_run_attack_on_tick(FlipFridState* context);
|
||||
void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context);
|
||||
void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context);
|
||||
@@ -1,160 +0,0 @@
|
||||
#include "flipfrid_scene_select_field.h"
|
||||
|
||||
void flipfrid_center_displayed_key(FlipFridState* context, uint8_t index) {
|
||||
char key_cstr[18];
|
||||
uint8_t key_len = 18;
|
||||
uint8_t str_index = (index * 3);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
int key_index = 0;
|
||||
|
||||
if(context->proto == EM4100) {
|
||||
key_len = 16;
|
||||
}
|
||||
if(context->proto == PAC) {
|
||||
key_len = 13;
|
||||
}
|
||||
if(context->proto == H10301) {
|
||||
key_len = 10;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->data[i] < 9) {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "0%X ", context->data[i]);
|
||||
} else {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "%X ", context->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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] = ' ';
|
||||
}
|
||||
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, display_menu);
|
||||
}
|
||||
|
||||
void flipfrid_scene_select_field_on_enter(FlipFridState* context) {
|
||||
furi_string_reset(context->notification_msg);
|
||||
}
|
||||
|
||||
void flipfrid_scene_select_field_on_exit(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_select_field_on_tick(FlipFridState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
const char* key_cstr = furi_string_get_cstr(context->data_str);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
|
||||
// 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:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->key_index > 0) {
|
||||
context->key_index = context->key_index - 1;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->key_index < nb_bytes) {
|
||||
context->key_index = context->key_index + 1;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneAttack;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->key_index = 0;
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneSelectFile;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Frame
|
||||
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 12, 5, AlignLeft, AlignTop, "Left and right: select byte");
|
||||
canvas_draw_str_aligned(canvas, 12, 15, AlignLeft, AlignTop, "Up and down: adjust byte");
|
||||
|
||||
char msg_index[18];
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
|
||||
canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignTop, msg_index);
|
||||
|
||||
flipfrid_center_displayed_key(context, context->key_index);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 45, AlignCenter, AlignTop, furi_string_get_cstr(context->notification_msg));
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../flipfrid.h"
|
||||
|
||||
void flipfrid_scene_select_field_on_enter(FlipFridState* context);
|
||||
void flipfrid_scene_select_field_on_exit(FlipFridState* context);
|
||||
void flipfrid_scene_select_field_on_tick(FlipFridState* context);
|
||||
void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context);
|
||||
void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context);
|
||||
void center_displayed_key(FlipFridState* context, uint8_t index);
|
||||
8
applications/external/ibtn_fuzzer/LICENSE.md
vendored
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* @xMasterX and @G4N4P4T1(made original version) 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.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1,12 +0,0 @@
|
||||
App(
|
||||
appid="ibtn_fuzzer",
|
||||
name="iButton Fuzzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="ibtnfuzzer_start",
|
||||
requires=["gui", "storage", "dialogs", "input", "notification"],
|
||||
stack_size=1 * 1024,
|
||||
order=15,
|
||||
fap_icon="ibutt_10px.png",
|
||||
fap_category="Tools",
|
||||
fap_icon_assets="images",
|
||||
)
|
||||
280
applications/external/ibtn_fuzzer/ibtnfuzzer.c
vendored
@@ -1,280 +0,0 @@
|
||||
#include "ibtnfuzzer.h"
|
||||
|
||||
#include "scene/ibtnfuzzer_scene_entrypoint.h"
|
||||
#include "scene/ibtnfuzzer_scene_load_file.h"
|
||||
#include "scene/ibtnfuzzer_scene_select_field.h"
|
||||
#include "scene/ibtnfuzzer_scene_run_attack.h"
|
||||
#include "scene/ibtnfuzzer_scene_load_custom_uids.h"
|
||||
|
||||
#define IBTNFUZZER_APP_FOLDER "/ext/ibtnfuzzer"
|
||||
|
||||
static void ibtnfuzzer_draw_callback(Canvas* const canvas, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
iBtnFuzzerState* ibtnfuzzer_state = ctx;
|
||||
furi_mutex_acquire(ibtnfuzzer_state->mutex, FuriWaitForever);
|
||||
|
||||
// Draw correct Canvas
|
||||
switch(ibtnfuzzer_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
ibtnfuzzer_scene_entrypoint_on_draw(canvas, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
ibtnfuzzer_scene_load_file_on_draw(canvas, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
ibtnfuzzer_scene_select_field_on_draw(canvas, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
ibtnfuzzer_scene_run_attack_on_draw(canvas, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
ibtnfuzzer_scene_load_custom_uids_on_draw(canvas, ibtnfuzzer_state);
|
||||
break;
|
||||
}
|
||||
|
||||
furi_mutex_release(ibtnfuzzer_state->mutex);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
|
||||
iBtnFuzzerEvent event = {
|
||||
.evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
static void ibtnfuzzer_timer_callback(FuriMessageQueue* event_queue) {
|
||||
furi_assert(event_queue);
|
||||
iBtnFuzzerEvent event = {
|
||||
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
||||
furi_message_queue_put(event_queue, &event, 25);
|
||||
}
|
||||
|
||||
iBtnFuzzerState* ibtnfuzzer_alloc() {
|
||||
iBtnFuzzerState* ibtnfuzzer = malloc(sizeof(iBtnFuzzerState));
|
||||
ibtnfuzzer->notification_msg = furi_string_alloc();
|
||||
ibtnfuzzer->attack_name = furi_string_alloc();
|
||||
ibtnfuzzer->proto_name = furi_string_alloc();
|
||||
ibtnfuzzer->data_str = furi_string_alloc();
|
||||
|
||||
ibtnfuzzer->main_menu_items[0] = furi_string_alloc_set("Default Values");
|
||||
ibtnfuzzer->main_menu_items[1] = furi_string_alloc_set("Load File");
|
||||
ibtnfuzzer->main_menu_items[2] = furi_string_alloc_set("Load UIDs from file");
|
||||
|
||||
ibtnfuzzer->main_menu_proto_items[0] = furi_string_alloc_set("DS1990");
|
||||
ibtnfuzzer->main_menu_proto_items[1] = furi_string_alloc_set("Metakom");
|
||||
ibtnfuzzer->main_menu_proto_items[2] = furi_string_alloc_set("Cyfral");
|
||||
|
||||
ibtnfuzzer->previous_scene = NoneScene;
|
||||
ibtnfuzzer->current_scene = SceneEntryPoint;
|
||||
ibtnfuzzer->is_running = true;
|
||||
ibtnfuzzer->is_attacking = false;
|
||||
ibtnfuzzer->key_index = 0;
|
||||
ibtnfuzzer->menu_index = 0;
|
||||
ibtnfuzzer->menu_proto_index = 0;
|
||||
|
||||
ibtnfuzzer->attack = iBtnFuzzerAttackDefaultValues;
|
||||
ibtnfuzzer->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
ibtnfuzzer->data[0] = 0x00;
|
||||
ibtnfuzzer->data[1] = 0x00;
|
||||
ibtnfuzzer->data[2] = 0x00;
|
||||
ibtnfuzzer->data[3] = 0x00;
|
||||
ibtnfuzzer->data[4] = 0x00;
|
||||
ibtnfuzzer->data[5] = 0x00;
|
||||
ibtnfuzzer->data[6] = 0x00;
|
||||
ibtnfuzzer->data[7] = 0x00;
|
||||
|
||||
ibtnfuzzer->payload[0] = 0x00;
|
||||
ibtnfuzzer->payload[1] = 0x00;
|
||||
ibtnfuzzer->payload[2] = 0x00;
|
||||
ibtnfuzzer->payload[3] = 0x00;
|
||||
ibtnfuzzer->payload[4] = 0x00;
|
||||
ibtnfuzzer->payload[5] = 0x00;
|
||||
ibtnfuzzer->payload[6] = 0x00;
|
||||
ibtnfuzzer->payload[7] = 0x00;
|
||||
|
||||
//Dialog
|
||||
ibtnfuzzer->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
return ibtnfuzzer;
|
||||
}
|
||||
|
||||
void ibtnfuzzer_free(iBtnFuzzerState* ibtnfuzzer) {
|
||||
//Dialog
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
notification_message(ibtnfuzzer->notify, &sequence_blink_stop);
|
||||
|
||||
// Strings
|
||||
furi_string_free(ibtnfuzzer->notification_msg);
|
||||
furi_string_free(ibtnfuzzer->attack_name);
|
||||
furi_string_free(ibtnfuzzer->proto_name);
|
||||
furi_string_free(ibtnfuzzer->data_str);
|
||||
|
||||
for(uint32_t i = 0; i < 3; i++) {
|
||||
furi_string_free(ibtnfuzzer->main_menu_items[i]);
|
||||
}
|
||||
|
||||
for(uint32_t i = 0; i < 3; i++) {
|
||||
furi_string_free(ibtnfuzzer->main_menu_proto_items[i]);
|
||||
}
|
||||
|
||||
// The rest
|
||||
free(ibtnfuzzer);
|
||||
}
|
||||
|
||||
// ENTRYPOINT
|
||||
int32_t ibtnfuzzer_start(void* p) {
|
||||
UNUSED(p);
|
||||
// Input
|
||||
FURI_LOG_I(TAG, "Initializing input");
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(iBtnFuzzerEvent));
|
||||
iBtnFuzzerState* ibtnfuzzer_state = ibtnfuzzer_alloc();
|
||||
|
||||
ibtnfuzzer_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
if(!ibtnfuzzer_state->mutex) {
|
||||
FURI_LOG_E(TAG, "cannot create mutex\r\n");
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
ibtnfuzzer_free(ibtnfuzzer_state);
|
||||
return 255;
|
||||
}
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(!storage_simply_mkdir(storage, IBTNFUZZER_APP_FOLDER)) {
|
||||
FURI_LOG_E(TAG, "Could not create folder %s", IBTNFUZZER_APP_FOLDER);
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
// Configure view port
|
||||
FURI_LOG_I(TAG, "Initializing viewport");
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, ibtnfuzzer_draw_callback, ibtnfuzzer_state);
|
||||
view_port_input_callback_set(view_port, ibtnfuzzer_input_callback, event_queue);
|
||||
|
||||
// Configure timer
|
||||
FURI_LOG_I(TAG, "Initializing timer");
|
||||
FuriTimer* timer =
|
||||
furi_timer_alloc(ibtnfuzzer_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");
|
||||
Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
// Init values
|
||||
iBtnFuzzerEvent event;
|
||||
while(ibtnfuzzer_state->is_running) {
|
||||
// Get next event
|
||||
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
|
||||
//furi_mutex_acquire(ibtnfuzzer_state->mutex, FuriWaitForever);
|
||||
if(event_status == FuriStatusOk) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
//Handle event key
|
||||
switch(ibtnfuzzer_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
ibtnfuzzer_scene_entrypoint_on_event(event, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
ibtnfuzzer_scene_load_file_on_event(event, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
ibtnfuzzer_scene_select_field_on_event(event, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
ibtnfuzzer_scene_run_attack_on_event(event, ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
ibtnfuzzer_scene_load_custom_uids_on_event(event, ibtnfuzzer_state);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if(event.evt_type == EventTypeTick) {
|
||||
//Handle event tick
|
||||
if(ibtnfuzzer_state->current_scene != ibtnfuzzer_state->previous_scene) {
|
||||
// Trigger Exit Scene
|
||||
switch(ibtnfuzzer_state->previous_scene) {
|
||||
case SceneEntryPoint:
|
||||
ibtnfuzzer_scene_entrypoint_on_exit(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
ibtnfuzzer_scene_load_file_on_exit(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
ibtnfuzzer_scene_select_field_on_exit(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
ibtnfuzzer_scene_run_attack_on_exit(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
ibtnfuzzer_scene_load_custom_uids_on_exit(ibtnfuzzer_state);
|
||||
break;
|
||||
case NoneScene:
|
||||
break;
|
||||
}
|
||||
|
||||
// Trigger Entry Scene
|
||||
switch(ibtnfuzzer_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
ibtnfuzzer_scene_entrypoint_on_enter(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
ibtnfuzzer_scene_load_file_on_enter(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
ibtnfuzzer_scene_select_field_on_enter(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
ibtnfuzzer_scene_run_attack_on_enter(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
ibtnfuzzer_scene_load_custom_uids_on_enter(ibtnfuzzer_state);
|
||||
break;
|
||||
}
|
||||
ibtnfuzzer_state->previous_scene = ibtnfuzzer_state->current_scene;
|
||||
}
|
||||
|
||||
// Trigger Tick Scene
|
||||
switch(ibtnfuzzer_state->current_scene) {
|
||||
case NoneScene:
|
||||
case SceneEntryPoint:
|
||||
ibtnfuzzer_scene_entrypoint_on_tick(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectFile:
|
||||
ibtnfuzzer_scene_load_file_on_tick(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneSelectField:
|
||||
ibtnfuzzer_scene_select_field_on_tick(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneAttack:
|
||||
ibtnfuzzer_scene_run_attack_on_tick(ibtnfuzzer_state);
|
||||
break;
|
||||
case SceneLoadCustomUids:
|
||||
ibtnfuzzer_scene_load_custom_uids_on_tick(ibtnfuzzer_state);
|
||||
break;
|
||||
}
|
||||
view_port_update(view_port);
|
||||
}
|
||||
}
|
||||
//furi_mutex_release(ibtnfuzzer_state->mutex);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
furi_timer_stop(timer);
|
||||
furi_timer_free(timer);
|
||||
|
||||
FURI_LOG_I(TAG, "Cleaning up");
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_mutex_free(ibtnfuzzer_state->mutex);
|
||||
ibtnfuzzer_free(ibtnfuzzer_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
94
applications/external/ibtn_fuzzer/ibtnfuzzer.h
vendored
@@ -1,94 +0,0 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <toolbox/stream/string_stream.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
|
||||
#include <ibtn_fuzzer_icons.h>
|
||||
|
||||
#include <lib/ibutton/ibutton_worker.h>
|
||||
#include <lib/ibutton/ibutton_key.h>
|
||||
|
||||
#define TAG "iBtnFuzzer"
|
||||
|
||||
typedef enum {
|
||||
iBtnFuzzerAttackDefaultValues,
|
||||
iBtnFuzzerAttackLoadFile,
|
||||
iBtnFuzzerAttackLoadFileCustomUids,
|
||||
} iBtnFuzzerAttacks;
|
||||
|
||||
typedef enum {
|
||||
DS1990,
|
||||
Metakom,
|
||||
Cyfral,
|
||||
} iBtnFuzzerProtos;
|
||||
|
||||
typedef enum {
|
||||
NoneScene,
|
||||
SceneEntryPoint,
|
||||
SceneSelectFile,
|
||||
SceneSelectField,
|
||||
SceneAttack,
|
||||
SceneLoadCustomUids,
|
||||
} iBtnFuzzerScene;
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
EventType evt_type;
|
||||
InputKey key;
|
||||
InputType input_type;
|
||||
} iBtnFuzzerEvent;
|
||||
|
||||
// STRUCTS
|
||||
typedef struct {
|
||||
FuriMutex* mutex;
|
||||
bool is_running;
|
||||
bool is_attacking;
|
||||
iBtnFuzzerScene current_scene;
|
||||
iBtnFuzzerScene previous_scene;
|
||||
NotificationApp* notify;
|
||||
u_int8_t menu_index;
|
||||
u_int8_t menu_proto_index;
|
||||
|
||||
FuriString* data_str;
|
||||
uint8_t data[8];
|
||||
uint8_t payload[8];
|
||||
uint8_t attack_step;
|
||||
iBtnFuzzerAttacks attack;
|
||||
iBtnFuzzerProtos proto;
|
||||
FuriString* attack_name;
|
||||
FuriString* proto_name;
|
||||
FuriString* main_menu_items[3];
|
||||
FuriString* main_menu_proto_items[3];
|
||||
|
||||
DialogsApp* dialogs;
|
||||
FuriString* notification_msg;
|
||||
uint8_t key_index;
|
||||
iButtonWorker* worker;
|
||||
iButtonKey* key;
|
||||
iButtonProtocolId keytype;
|
||||
iButtonProtocols* protocols;
|
||||
bool workr_rund;
|
||||
bool enter_rerun;
|
||||
bool attack_stop_called;
|
||||
|
||||
uint8_t time_between_cards;
|
||||
|
||||
// Used for custom dictionnary
|
||||
Stream* uids_stream;
|
||||
} iBtnFuzzerState;
|
||||
|
Before Width: | Height: | Size: 304 B |
@@ -1,201 +0,0 @@
|
||||
#include "ibtnfuzzer_scene_entrypoint.h"
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_menu_callback(
|
||||
iBtnFuzzerState* context,
|
||||
uint32_t index,
|
||||
uint32_t proto_index) {
|
||||
switch(index) {
|
||||
case iBtnFuzzerAttackDefaultValues:
|
||||
context->attack = iBtnFuzzerAttackDefaultValues;
|
||||
context->current_scene = SceneAttack;
|
||||
furi_string_set(context->attack_name, "Default Values");
|
||||
break;
|
||||
case iBtnFuzzerAttackLoadFile:
|
||||
context->attack = iBtnFuzzerAttackLoadFile;
|
||||
context->current_scene = SceneSelectFile;
|
||||
furi_string_set(context->attack_name, "Load File");
|
||||
break;
|
||||
case iBtnFuzzerAttackLoadFileCustomUids:
|
||||
context->attack = iBtnFuzzerAttackLoadFileCustomUids;
|
||||
context->current_scene = SceneLoadCustomUids;
|
||||
furi_string_set(context->attack_name, "Load Custom UIDs");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(proto_index) {
|
||||
case DS1990:
|
||||
context->proto = DS1990;
|
||||
furi_string_set(context->proto_name, "DS1990");
|
||||
break;
|
||||
case Metakom:
|
||||
context->proto = Metakom;
|
||||
furi_string_set(context->proto_name, "Metakom");
|
||||
break;
|
||||
case Cyfral:
|
||||
context->proto = Cyfral;
|
||||
furi_string_set(context->proto_name, "Cyfral");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_enter(iBtnFuzzerState* context) {
|
||||
// Clear the previous payload
|
||||
context->payload[0] = 0x00;
|
||||
context->payload[1] = 0x00;
|
||||
context->payload[2] = 0x00;
|
||||
context->payload[3] = 0x00;
|
||||
context->payload[4] = 0x00;
|
||||
context->payload[5] = 0x00;
|
||||
context->payload[6] = 0x00;
|
||||
context->payload[7] = 0x00;
|
||||
|
||||
context->menu_index = 0;
|
||||
/*for(uint32_t i = 0; i < 4; i++) {
|
||||
menu_items[i] = furi_string_alloc();
|
||||
}*/
|
||||
|
||||
context->menu_proto_index = 0;
|
||||
/*for(uint32_t i = 0; i < 4; i++) {
|
||||
menu_proto_items[i] = furi_string_alloc();
|
||||
}*/
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_exit(iBtnFuzzerState* context) {
|
||||
context->enter_rerun = false;
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_tick(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
if(context->menu_index < iBtnFuzzerAttackLoadFileCustomUids) {
|
||||
context->menu_index++;
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
if(context->menu_index > iBtnFuzzerAttackDefaultValues) {
|
||||
context->menu_index--;
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->menu_proto_index > DS1990) {
|
||||
context->menu_proto_index--;
|
||||
} else if(context->menu_proto_index == DS1990) {
|
||||
context->menu_proto_index = Cyfral;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->menu_proto_index < Cyfral) {
|
||||
context->menu_proto_index++;
|
||||
} else if(context->menu_proto_index == Cyfral) {
|
||||
context->menu_proto_index = DS1990;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
ibtnfuzzer_scene_entrypoint_menu_callback(
|
||||
context, context->menu_index, context->menu_proto_index);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->is_running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_draw(Canvas* canvas, iBtnFuzzerState* context) {
|
||||
if(!context->enter_rerun) {
|
||||
ibtnfuzzer_scene_entrypoint_on_enter(context);
|
||||
context->enter_rerun = true;
|
||||
}
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(context->main_menu_items != NULL) {
|
||||
if(context->main_menu_items[context->menu_index] != NULL) {
|
||||
if(context->menu_index > iBtnFuzzerAttackDefaultValues) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
24,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index - 1]));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
36,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index]));
|
||||
|
||||
if(context->menu_index < iBtnFuzzerAttackLoadFileCustomUids) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
48,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(context->main_menu_items[context->menu_index + 1]));
|
||||
}
|
||||
|
||||
if(context->menu_proto_index > DS1990) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(
|
||||
context->main_menu_proto_items[context->menu_proto_index - 1]));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 27, 4, AlignCenter, AlignTop, "<");
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
if(context->main_menu_proto_items[context->menu_proto_index] != NULL) {
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
4,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(
|
||||
context->main_menu_proto_items[context->menu_proto_index]));
|
||||
}
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 101, 4, AlignCenter, AlignTop, ">");
|
||||
|
||||
if(context->menu_proto_index < Cyfral) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
-12,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
furi_string_get_cstr(
|
||||
context->main_menu_proto_items[context->menu_proto_index + 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "../ibtnfuzzer.h"
|
||||
|
||||
void ibtnfuzzer_scene_entrypoint_on_enter(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_entrypoint_on_exit(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_entrypoint_on_tick(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_entrypoint_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_entrypoint_on_draw(Canvas* canvas, iBtnFuzzerState* context);
|
||||
@@ -1,86 +0,0 @@
|
||||
#include "ibtnfuzzer_scene_load_custom_uids.h"
|
||||
#include "ibtnfuzzer_scene_run_attack.h"
|
||||
#include "ibtnfuzzer_scene_entrypoint.h"
|
||||
|
||||
#define IBTNFUZZER_UIDS_EXTENSION ".txt"
|
||||
#define IBTNFUZZER_APP_PATH_FOLDER "/ext/ibtnfuzzer"
|
||||
|
||||
bool ibtnfuzzer_load_uids(iBtnFuzzerState* context, const char* file_path) {
|
||||
bool result = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
context->uids_stream = buffered_file_stream_alloc(storage);
|
||||
result =
|
||||
buffered_file_stream_open(context->uids_stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
// Close if loading fails
|
||||
if(!result) {
|
||||
buffered_file_stream_close(context->uids_stream);
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ibtnfuzzer_load_custom_uids_from_file(iBtnFuzzerState* context) {
|
||||
// Input events and views are managed by file_select
|
||||
FuriString* uid_path;
|
||||
uid_path = furi_string_alloc();
|
||||
furi_string_set(uid_path, IBTNFUZZER_APP_PATH_FOLDER);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, IBTNFUZZER_UIDS_EXTENSION, &I_ibutt_10px);
|
||||
browser_options.base_path = IBTNFUZZER_APP_PATH_FOLDER;
|
||||
browser_options.hide_ext = false;
|
||||
|
||||
bool res = dialog_file_browser_show(context->dialogs, uid_path, uid_path, &browser_options);
|
||||
|
||||
if(res) {
|
||||
res = ibtnfuzzer_load_uids(context, furi_string_get_cstr(uid_path));
|
||||
}
|
||||
|
||||
furi_string_free(uid_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_enter(iBtnFuzzerState* context) {
|
||||
if(ibtnfuzzer_load_custom_uids_from_file(context)) {
|
||||
// Force context loading
|
||||
ibtnfuzzer_scene_run_attack_on_enter(context);
|
||||
context->current_scene = SceneAttack;
|
||||
} else {
|
||||
ibtnfuzzer_scene_entrypoint_on_enter(context);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_exit(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_tick(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
case InputKeyUp:
|
||||
case InputKeyLeft:
|
||||
case InputKeyRight:
|
||||
case InputKeyOk:
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_draw(Canvas* canvas, iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(canvas);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../ibtnfuzzer.h"
|
||||
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_enter(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_exit(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_tick(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_custom_uids_on_draw(Canvas* canvas, iBtnFuzzerState* context);
|
||||
bool ibtnfuzzer_load_custom_uids_from_file(iBtnFuzzerState* context);
|
||||
@@ -1,293 +0,0 @@
|
||||
#include "ibtnfuzzer_scene_load_file.h"
|
||||
#include "ibtnfuzzer_scene_entrypoint.h"
|
||||
|
||||
#define IBUTTON_FUZZER_APP_EXTENSION ".ibtn"
|
||||
#define IBUTTON_FUZZER_APP_PATH_FOLDER "/ext/ibutton"
|
||||
|
||||
bool ibtnfuzzer_load(iBtnFuzzerState* context, const char* file_path) {
|
||||
bool result = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
bool key_v2 = false;
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Error open file");
|
||||
break;
|
||||
}
|
||||
|
||||
// FileType
|
||||
if(!flipper_format_read_string(fff_data_file, "Filetype", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Filetype");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Filetypes");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Filetype: %s", furi_string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
// Key type
|
||||
if(!flipper_format_read_string(fff_data_file, "Key type", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Key type, checking for typ2..");
|
||||
|
||||
if(!flipper_format_rewind(fff_data_file)) {
|
||||
FURI_LOG_E(TAG, "Failed to rewind file");
|
||||
break;
|
||||
}
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(
|
||||
context->notification_msg, "Missing or incorrect Protocol or Key type");
|
||||
break;
|
||||
}
|
||||
FURI_LOG_I(TAG, "Key type V2: %s", furi_string_get_cstr(temp_str));
|
||||
key_v2 = true;
|
||||
|
||||
if(context->proto == DS1990) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "DS1990") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == Cyfral) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "Cyfral") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "Metakom") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key type: %s", furi_string_get_cstr(temp_str));
|
||||
|
||||
if(context->proto == DS1990) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "Dallas") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == Cyfral) {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "Cyfral") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(strcmp(furi_string_get_cstr(temp_str), "Metakom") != 0) {
|
||||
FURI_LOG_E(TAG, "Unsupported Key type");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Unsupported Key type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!key_v2) {
|
||||
// Data
|
||||
if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Data");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Key");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", furi_string_get_cstr(context->data_str));
|
||||
|
||||
if(context->proto == DS1990) {
|
||||
if(furi_string_size(context->data_str) != 23) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else if(context->proto == Cyfral) {
|
||||
if(furi_string_size(context->data_str) != 5) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(furi_string_size(context->data_str) != 11) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = furi_string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = furi_string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
temp_str2[2] = '\0';
|
||||
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Data
|
||||
if(context->proto == DS1990) {
|
||||
if(!flipper_format_read_string(fff_data_file, "Rom Data", context->data_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Rom Data");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Rom Data");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", furi_string_get_cstr(context->data_str));
|
||||
|
||||
if(furi_string_size(context->data_str) != 23) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = furi_string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = furi_string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
temp_str2[2] = '\0';
|
||||
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||
}
|
||||
}
|
||||
} else if(context->proto == Cyfral) {
|
||||
if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Data");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Data");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", furi_string_get_cstr(context->data_str));
|
||||
|
||||
if(furi_string_size(context->data_str) != 5) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = furi_string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = furi_string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
temp_str2[2] = '\0';
|
||||
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect Data");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Missing or incorrect Data");
|
||||
break;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Key: %s", furi_string_get_cstr(context->data_str));
|
||||
|
||||
if(furi_string_size(context->data_str) != 11) {
|
||||
FURI_LOG_E(TAG, "Incorrect Key length");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Incorrect Key length");
|
||||
break;
|
||||
}
|
||||
|
||||
// String to uint8_t
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
char temp_str2[3];
|
||||
temp_str2[0] = furi_string_get_cstr(context->data_str)[i * 3];
|
||||
temp_str2[1] = furi_string_get_cstr(context->data_str)[i * 3 + 1];
|
||||
temp_str2[2] = '\0';
|
||||
context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
} while(0);
|
||||
furi_string_free(temp_str);
|
||||
flipper_format_free(fff_data_file);
|
||||
if(result) {
|
||||
FURI_LOG_I(TAG, "Loaded successfully");
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, "Source loaded.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_enter(iBtnFuzzerState* context) {
|
||||
if(ibtnfuzzer_load_protocol_from_file(context)) {
|
||||
context->current_scene = SceneSelectField;
|
||||
} else {
|
||||
ibtnfuzzer_scene_entrypoint_on_enter(context);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_exit(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_tick(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
case InputKeyUp:
|
||||
case InputKeyLeft:
|
||||
case InputKeyRight:
|
||||
case InputKeyOk:
|
||||
case InputKeyBack:
|
||||
context->current_scene = SceneEntryPoint;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_draw(Canvas* canvas, iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
UNUSED(canvas);
|
||||
}
|
||||
|
||||
bool ibtnfuzzer_load_protocol_from_file(iBtnFuzzerState* context) {
|
||||
FuriString* user_file_path;
|
||||
user_file_path = furi_string_alloc();
|
||||
furi_string_set(user_file_path, IBUTTON_FUZZER_APP_PATH_FOLDER);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, IBUTTON_FUZZER_APP_EXTENSION, &I_ibutt_10px);
|
||||
browser_options.base_path = IBUTTON_FUZZER_APP_PATH_FOLDER;
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
bool res = dialog_file_browser_show(
|
||||
context->dialogs, user_file_path, user_file_path, &browser_options);
|
||||
|
||||
if(res) {
|
||||
res = ibtnfuzzer_load(context, furi_string_get_cstr(user_file_path));
|
||||
}
|
||||
|
||||
furi_string_free(user_file_path);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../ibtnfuzzer.h"
|
||||
|
||||
void ibtnfuzzer_scene_load_file_on_enter(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_file_on_exit(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_file_on_tick(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_file_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_load_file_on_draw(Canvas* canvas, iBtnFuzzerState* context);
|
||||
bool ibtnfuzzer_load_protocol_from_file(iBtnFuzzerState* context);
|
||||
@@ -1,501 +0,0 @@
|
||||
#include "ibtnfuzzer_scene_run_attack.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
uint8_t counter = 0;
|
||||
|
||||
uint8_t id_list_ds1990[18][8] = {
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x5A, 0x36, 0x00, 0xE1}, //– код универсального ключа, для Vizit
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x5A, 0x56, 0x00, 0xBB}, //- проверен работает
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x00, 0x00, 0x00, 0x77}, //- проверен работает
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x0A, 0x00, 0x00, 0x1D}, //- проверен работает Визит иногда КЕЙМАНЫ
|
||||
{0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F}, //- проверен(метаком, цифрал, ВИЗИТ).
|
||||
{0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x9B}, //- проверен Визит, Метакомы, КОНДОР
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14}, //???-Открываает 98% Метаком и некоторые Цифрал
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x19, 0xFF}, //???-Отлично работает на старых домофонах
|
||||
{0x01, 0x6F, 0x2E, 0x88, 0x8A, 0x00, 0x00, 0x4D}, //???-Открывать что-то должен
|
||||
{0x01, 0x53, 0xD4, 0xFE, 0x00, 0x00, 0x7E, 0x88}, //???-Cyfral, Metakom
|
||||
{0x01, 0x53, 0xD4, 0xFE, 0x00, 0x00, 0x00, 0x6F}, //???-домофоны Визит (Vizit) - до 99%
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D}, //???-домофоны Cyfral CCD-20 - до 70%
|
||||
{0x01, 0x00, 0xBE, 0x11, 0xAA, 0x00, 0x00, 0xFB}, //???-домофоны Кейман (KEYMAN)
|
||||
{0x01, 0x76, 0xB8, 0x2E, 0x0F, 0x00, 0x00, 0x5C}, //???-домофоны Форвард
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14}, // Only FF
|
||||
{0x01, 0x78, 0x00, 0x48, 0xFD, 0xFF, 0xFF, 0xD1}, // StarNew Uni5
|
||||
{0x01, 0xA9, 0xE4, 0x3C, 0x09, 0x00, 0x00, 0xE6}, // Eltis Uni
|
||||
};
|
||||
|
||||
uint8_t id_list_metakom[17][4] = {
|
||||
{0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d}, // ??
|
||||
{0x34, 0x00, 0x29, 0x3d}, // ??
|
||||
{0x04, 0xdf, 0x00, 0x00}, // ??
|
||||
{0xCA, 0xCA, 0xCA, 0xCA}, // ??
|
||||
};
|
||||
|
||||
uint8_t id_list_cyfral[16][2] = {
|
||||
{0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34}, // Incremental UID
|
||||
{0x56, 0x34}, // Decremental UID
|
||||
{0xCA, 0xCA}, // ??
|
||||
{0x8E, 0xC9}, // Elevator code
|
||||
{0x6A, 0x50}, // VERY fresh code from smartkey
|
||||
};
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_enter(iBtnFuzzerState* context) {
|
||||
context->time_between_cards = 8;
|
||||
context->attack_step = 0;
|
||||
context->attack_stop_called = false;
|
||||
context->protocols = ibutton_protocols_alloc();
|
||||
context->key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(context->protocols));
|
||||
context->worker = ibutton_worker_alloc(context->protocols);
|
||||
if(context->proto == Metakom) {
|
||||
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Metakom");
|
||||
} else if(context->proto == Cyfral) {
|
||||
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Cyfral");
|
||||
} else {
|
||||
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "DS1990");
|
||||
}
|
||||
context->workr_rund = false;
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_exit(iBtnFuzzerState* context) {
|
||||
if(context->workr_rund) {
|
||||
ibutton_worker_stop(context->worker);
|
||||
ibutton_worker_stop_thread(context->worker);
|
||||
context->workr_rund = false;
|
||||
}
|
||||
ibutton_key_free(context->key);
|
||||
ibutton_worker_free(context->worker);
|
||||
ibutton_protocols_free(context->protocols);
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) {
|
||||
if(context->is_attacking) {
|
||||
if(1 == counter) {
|
||||
ibutton_worker_start_thread(context->worker);
|
||||
ibutton_key_set_protocol_id(context->key, context->keytype);
|
||||
iButtonEditableData data;
|
||||
ibutton_protocols_get_editable_data(context->protocols, context->key, &data);
|
||||
data.size = sizeof(context->payload);
|
||||
for(size_t i = 0; i < data.size; i++) {
|
||||
data.ptr[i] = context->payload[i];
|
||||
}
|
||||
|
||||
ibutton_worker_emulate_start(context->worker, context->key);
|
||||
context->workr_rund = true;
|
||||
} else if(0 == counter) {
|
||||
if(context->workr_rund) {
|
||||
ibutton_worker_stop(context->worker);
|
||||
ibutton_worker_stop_thread(context->worker);
|
||||
context->workr_rund = false;
|
||||
furi_delay_ms(500);
|
||||
}
|
||||
switch(context->attack) {
|
||||
case iBtnFuzzerAttackDefaultValues:
|
||||
if(context->proto == DS1990) {
|
||||
context->payload[0] = id_list_ds1990[context->attack_step][0];
|
||||
context->payload[1] = id_list_ds1990[context->attack_step][1];
|
||||
context->payload[2] = id_list_ds1990[context->attack_step][2];
|
||||
context->payload[3] = id_list_ds1990[context->attack_step][3];
|
||||
context->payload[4] = id_list_ds1990[context->attack_step][4];
|
||||
context->payload[5] = id_list_ds1990[context->attack_step][5];
|
||||
context->payload[6] = id_list_ds1990[context->attack_step][6];
|
||||
context->payload[7] = id_list_ds1990[context->attack_step][7];
|
||||
|
||||
if(context->attack_step == 17) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == Metakom) {
|
||||
context->payload[0] = id_list_metakom[context->attack_step][0];
|
||||
context->payload[1] = id_list_metakom[context->attack_step][1];
|
||||
context->payload[2] = id_list_metakom[context->attack_step][2];
|
||||
context->payload[3] = id_list_metakom[context->attack_step][3];
|
||||
|
||||
if(context->attack_step == 16) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = id_list_cyfral[context->attack_step][0];
|
||||
context->payload[1] = id_list_cyfral[context->attack_step][1];
|
||||
|
||||
if(context->attack_step == 15) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case iBtnFuzzerAttackLoadFile:
|
||||
if(context->proto == DS1990) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
context->payload[4] = context->data[4];
|
||||
context->payload[5] = context->data[5];
|
||||
context->payload[6] = context->data[6];
|
||||
context->payload[7] = context->data[7];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == Cyfral) {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
context->payload[0] = context->data[0];
|
||||
context->payload[1] = context->data[1];
|
||||
context->payload[2] = context->data[2];
|
||||
context->payload[3] = context->data[3];
|
||||
|
||||
context->payload[context->key_index] = context->attack_step;
|
||||
|
||||
if(context->attack_step == 255) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
break;
|
||||
} else {
|
||||
context->attack_step++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case iBtnFuzzerAttackLoadFileCustomUids:
|
||||
if(context->proto == DS1990) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 17) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(furi_string_size(context->data_str) != 17) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else if(context->proto == Cyfral) {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 5) break;
|
||||
break;
|
||||
}
|
||||
if(end_of_list) break;
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(furi_string_size(context->data_str) != 5) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 2; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
bool end_of_list = false;
|
||||
while(true) {
|
||||
furi_string_reset(context->data_str);
|
||||
if(!stream_read_line(context->uids_stream, context->data_str)) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
stream_rewind(context->uids_stream);
|
||||
end_of_list = true;
|
||||
break;
|
||||
};
|
||||
if(furi_string_get_char(context->data_str, 0) == '#') continue;
|
||||
if(furi_string_size(context->data_str) != 9) break;
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, furi_string_get_cstr(context->data_str));
|
||||
if(end_of_list) break;
|
||||
if(furi_string_size(context->data_str) != 9) {
|
||||
context->attack_step = 0;
|
||||
counter = 0;
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_error);
|
||||
break;
|
||||
};
|
||||
|
||||
// string is valid, parse it in context->payload
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
char temp_str[3];
|
||||
temp_str[0] = furi_string_get_cstr(context->data_str)[i * 2];
|
||||
temp_str[1] = furi_string_get_cstr(context->data_str)[i * 2 + 1];
|
||||
temp_str[2] = '\0';
|
||||
context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(counter > context->time_between_cards) {
|
||||
counter = 0;
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
switch(event.key) {
|
||||
case InputKeyDown:
|
||||
break;
|
||||
case InputKeyUp:
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards > 4) {
|
||||
context->time_between_cards--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards < 80) {
|
||||
context->time_between_cards++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
counter = 0;
|
||||
if(!context->is_attacking) {
|
||||
notification_message(context->notify, &sequence_blink_start_blue);
|
||||
context->is_attacking = true;
|
||||
} else {
|
||||
context->is_attacking = false;
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
notification_message(context->notify, &sequence_single_vibro);
|
||||
}
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->is_attacking = false;
|
||||
counter = 0;
|
||||
|
||||
notification_message(context->notify, &sequence_blink_stop);
|
||||
if(context->attack_stop_called) {
|
||||
context->attack_stop_called = false;
|
||||
context->attack_step = 0;
|
||||
if(context->attack == iBtnFuzzerAttackLoadFileCustomUids) {
|
||||
furi_string_reset(context->data_str);
|
||||
stream_rewind(context->uids_stream);
|
||||
buffered_file_stream_close(context->uids_stream);
|
||||
}
|
||||
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneEntryPoint;
|
||||
}
|
||||
|
||||
context->attack_stop_called = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(event.input_type == InputTypeLong) {
|
||||
switch(event.key) {
|
||||
case InputKeyLeft:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards > 4) {
|
||||
if((context->time_between_cards - 10) > 4) {
|
||||
context->time_between_cards -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(!context->is_attacking) {
|
||||
if(context->time_between_cards < 80) {
|
||||
context->time_between_cards += 10;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_draw(Canvas* canvas, iBtnFuzzerState* 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, 2, AlignCenter, AlignTop, furi_string_get_cstr(context->attack_name));
|
||||
|
||||
char uid[25];
|
||||
char speed[16];
|
||||
if(context->proto == Metakom) {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3]);
|
||||
} else if(context->proto == Cyfral) {
|
||||
snprintf(uid, sizeof(uid), "%02X:%02X", context->payload[0], context->payload[1]);
|
||||
} else {
|
||||
snprintf(
|
||||
uid,
|
||||
sizeof(uid),
|
||||
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
context->payload[0],
|
||||
context->payload[1],
|
||||
context->payload[2],
|
||||
context->payload[3],
|
||||
context->payload[4],
|
||||
context->payload[5],
|
||||
context->payload[6],
|
||||
context->payload[7]);
|
||||
}
|
||||
|
||||
canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignTop, uid);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 26, AlignCenter, AlignTop, furi_string_get_cstr(context->proto_name));
|
||||
|
||||
snprintf(speed, sizeof(speed), "Time delay: %d", context->time_between_cards);
|
||||
|
||||
//canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Speed:");
|
||||
canvas_draw_str_aligned(canvas, 64, 14, AlignCenter, AlignTop, speed);
|
||||
//char start_stop_msg[20];
|
||||
if(context->is_attacking) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
//snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_left(canvas, "TD -");
|
||||
elements_button_right(canvas, "+ TD");
|
||||
}
|
||||
//canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include "../ibtnfuzzer.h"
|
||||
|
||||
void ibtnfuzzer_scene_run_attack_on_enter(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_run_attack_on_exit(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_run_attack_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_run_attack_on_draw(Canvas* canvas, iBtnFuzzerState* context);
|
||||
@@ -1,160 +0,0 @@
|
||||
#include "ibtnfuzzer_scene_select_field.h"
|
||||
|
||||
void ibtnfuzzer_center_displayed_key(iBtnFuzzerState* context, uint8_t index) {
|
||||
char key_cstr[25];
|
||||
uint8_t key_len = 25;
|
||||
uint8_t str_index = (index * 3);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
int key_index = 0;
|
||||
|
||||
if(context->proto == DS1990) {
|
||||
key_len = 25;
|
||||
}
|
||||
if(context->proto == Metakom) {
|
||||
key_len = 13;
|
||||
}
|
||||
if(context->proto == Cyfral) {
|
||||
key_len = 7;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->data[i] < 9) {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "0%X ", context->data[i]);
|
||||
} else {
|
||||
key_index +=
|
||||
snprintf(&key_cstr[key_index], key_len - key_index, "%X ", context->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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] = ' ';
|
||||
}
|
||||
|
||||
furi_string_reset(context->notification_msg);
|
||||
furi_string_set(context->notification_msg, display_menu);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_enter(iBtnFuzzerState* context) {
|
||||
furi_string_reset(context->notification_msg);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_exit(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_tick(iBtnFuzzerState* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context) {
|
||||
if(event.evt_type == EventTypeKey) {
|
||||
if(event.input_type == InputTypeShort) {
|
||||
const char* key_cstr = furi_string_get_cstr(context->data_str);
|
||||
int data_len = sizeof(context->data) / sizeof(context->data[0]);
|
||||
|
||||
// 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:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyUp:
|
||||
for(uint8_t i = 0; i < data_len; i++) {
|
||||
if(context->key_index == i) {
|
||||
context->data[i] = (context->data[i] + 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(context->key_index > 0) {
|
||||
context->key_index = context->key_index - 1;
|
||||
}
|
||||
break;
|
||||
case InputKeyRight:
|
||||
if(context->key_index < nb_bytes) {
|
||||
context->key_index = context->key_index + 1;
|
||||
}
|
||||
break;
|
||||
case InputKeyOk:
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneAttack;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
context->key_index = 0;
|
||||
furi_string_reset(context->notification_msg);
|
||||
context->current_scene = SceneSelectFile;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_draw(Canvas* canvas, iBtnFuzzerState* context) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Frame
|
||||
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 12, 5, AlignLeft, AlignTop, "Left and right: select byte");
|
||||
canvas_draw_str_aligned(canvas, 12, 15, AlignLeft, AlignTop, "Up and down: adjust byte");
|
||||
|
||||
char msg_index[18];
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
|
||||
canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignTop, msg_index);
|
||||
|
||||
ibtnfuzzer_center_displayed_key(context, context->key_index);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 45, AlignCenter, AlignTop, furi_string_get_cstr(context->notification_msg));
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../ibtnfuzzer.h"
|
||||
|
||||
void ibtnfuzzer_scene_select_field_on_enter(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_select_field_on_exit(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_select_field_on_tick(iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_select_field_on_event(iBtnFuzzerEvent event, iBtnFuzzerState* context);
|
||||
void ibtnfuzzer_scene_select_field_on_draw(Canvas* canvas, iBtnFuzzerState* context);
|
||||
void center_displayed_key(iBtnFuzzerState* context, uint8_t index);
|
||||
49
applications/external/multi_fuzzer/application.fam
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
App(
|
||||
appid="fuzzer_ibtn",
|
||||
name="iButton Fuzzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="fuzzer_start_ibtn",
|
||||
requires=[
|
||||
"gui",
|
||||
"storage",
|
||||
"dialogs",
|
||||
"input",
|
||||
"notification",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
fap_icon="icons/ibutt_10px.png",
|
||||
fap_category="Tools",
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="worker",
|
||||
cdefines=["IBUTTON_PROTOCOL"],
|
||||
),
|
||||
],
|
||||
fap_icon_assets="icons",
|
||||
fap_icon_assets_symbol="fuzzer",
|
||||
)
|
||||
|
||||
App(
|
||||
appid="fuzzer_rfid",
|
||||
name="RFID Fuzzer",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="fuzzer_start_rfid",
|
||||
requires=[
|
||||
"gui",
|
||||
"storage",
|
||||
"dialogs",
|
||||
"input",
|
||||
"notification",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
fap_icon="icons/rfid_10px.png",
|
||||
fap_category="Tools",
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="worker",
|
||||
cdefines=["RFID_125_PROTOCOL"],
|
||||
),
|
||||
],
|
||||
fap_icon_assets="icons",
|
||||
fap_icon_assets_symbol="fuzzer",
|
||||
)
|
||||
160
applications/external/multi_fuzzer/fuzzer.c
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
#include "fuzzer_i.h"
|
||||
#include "helpers/fuzzer_types.h"
|
||||
|
||||
static bool fuzzer_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool fuzzer_app_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void fuzzer_app_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
PacsFuzzerApp* fuzzer_app_alloc() {
|
||||
PacsFuzzerApp* app = malloc(sizeof(PacsFuzzerApp));
|
||||
|
||||
app->fuzzer_state.menu_index = 0;
|
||||
app->fuzzer_state.proto_index = 0;
|
||||
|
||||
app->worker = fuzzer_worker_alloc();
|
||||
app->payload = fuzzer_payload_alloc();
|
||||
|
||||
app->file_path = furi_string_alloc();
|
||||
|
||||
// GUI
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
// Dialog
|
||||
app->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
// Open Notification record
|
||||
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// View Dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
|
||||
// Popup
|
||||
app->popup = popup_alloc();
|
||||
view_dispatcher_add_view(app->view_dispatcher, FuzzerViewIDPopup, popup_get_view(app->popup));
|
||||
|
||||
// Main view
|
||||
app->main_view = fuzzer_view_main_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FuzzerViewIDMain, fuzzer_view_main_get_view(app->main_view));
|
||||
|
||||
// Attack view
|
||||
app->attack_view = fuzzer_view_attack_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, FuzzerViewIDAttack, fuzzer_view_attack_get_view(app->attack_view));
|
||||
|
||||
// FieldEditor view
|
||||
app->field_editor_view = fuzzer_view_field_editor_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
FuzzerViewIDFieldEditor,
|
||||
fuzzer_view_field_editor_get_view(app->field_editor_view));
|
||||
|
||||
app->scene_manager = scene_manager_alloc(&fuzzer_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, fuzzer_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, fuzzer_app_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, fuzzer_app_tick_event_callback, 100);
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, FuzzerSceneMain);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void fuzzer_app_free(PacsFuzzerApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Remote view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDMain);
|
||||
fuzzer_view_main_free(app->main_view);
|
||||
|
||||
// Attack view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDAttack);
|
||||
fuzzer_view_attack_free(app->attack_view);
|
||||
|
||||
// FieldEditor view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDFieldEditor);
|
||||
fuzzer_view_field_editor_free(app->field_editor_view);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(app->view_dispatcher, FuzzerViewIDPopup);
|
||||
popup_free(app->popup);
|
||||
|
||||
scene_manager_free(app->scene_manager);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
// Dialog
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
app->notifications = NULL;
|
||||
|
||||
furi_string_free(app->file_path);
|
||||
|
||||
fuzzer_payload_free(app->payload);
|
||||
fuzzer_worker_free(app->worker);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t fuzzer_start_ibtn(void* p) {
|
||||
UNUSED(p);
|
||||
PacsFuzzerApp* fuzzer_app = fuzzer_app_alloc();
|
||||
|
||||
FuzzerConsts app_const = {
|
||||
.custom_dict_folder = "/ext/ibtnfuzzer",
|
||||
.custom_dict_extension = ".txt",
|
||||
.key_extension = ".ibtn",
|
||||
.path_key_folder = "/ext/ibutton",
|
||||
.key_icon = &I_ibutt_10px,
|
||||
};
|
||||
fuzzer_app->fuzzer_const = &app_const;
|
||||
|
||||
view_dispatcher_run(fuzzer_app->view_dispatcher);
|
||||
|
||||
fuzzer_app_free(fuzzer_app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t fuzzer_start_rfid(void* p) {
|
||||
UNUSED(p);
|
||||
PacsFuzzerApp* fuzzer_app = fuzzer_app_alloc();
|
||||
|
||||
FuzzerConsts app_const = {
|
||||
.custom_dict_folder = "/ext/rfidfuzzer",
|
||||
.custom_dict_extension = ".txt",
|
||||
.key_extension = ".rfid",
|
||||
.path_key_folder = "/ext/lfrfid",
|
||||
.key_icon = &I_125_10px,
|
||||
};
|
||||
fuzzer_app->fuzzer_const = &app_const;
|
||||
|
||||
view_dispatcher_run(fuzzer_app->view_dispatcher);
|
||||
|
||||
fuzzer_app_free(fuzzer_app);
|
||||
return 0;
|
||||
}
|
||||
55
applications/external/multi_fuzzer/fuzzer_i.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/popup.h>
|
||||
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include "scenes/fuzzer_scene.h"
|
||||
#include "views/main_menu.h"
|
||||
#include "views/attack.h"
|
||||
#include "views/field_editor.h"
|
||||
|
||||
#include "helpers/fuzzer_types.h"
|
||||
#include "lib/worker/fake_worker.h"
|
||||
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
#include "fuzzer_icons.h"
|
||||
|
||||
#define FUZZ_TIME_DELAY_MAX (80)
|
||||
|
||||
typedef struct {
|
||||
const char* custom_dict_extension;
|
||||
const char* custom_dict_folder;
|
||||
const char* key_extension;
|
||||
const char* path_key_folder;
|
||||
const Icon* key_icon;
|
||||
} FuzzerConsts;
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
|
||||
Popup* popup;
|
||||
DialogsApp* dialogs;
|
||||
FuzzerViewMain* main_view;
|
||||
FuzzerViewAttack* attack_view;
|
||||
FuzzerViewFieldEditor* field_editor_view;
|
||||
|
||||
FuriString* file_path;
|
||||
|
||||
FuzzerState fuzzer_state;
|
||||
FuzzerConsts* fuzzer_const;
|
||||
|
||||
FuzzerWorker* worker;
|
||||
FuzzerPayload* payload;
|
||||
} PacsFuzzerApp;
|
||||
17
applications/external/multi_fuzzer/helpers/fuzzer_custom_event.h
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
|
||||
// FuzzerCustomEvent
|
||||
FuzzerCustomEventViewMainBack = 100,
|
||||
FuzzerCustomEventViewMainOk,
|
||||
FuzzerCustomEventViewMainPopupErr,
|
||||
|
||||
FuzzerCustomEventViewAttackBack,
|
||||
FuzzerCustomEventViewAttackOk,
|
||||
// FuzzerCustomEventViewAttackTick, // now not use
|
||||
FuzzerCustomEventViewAttackEnd,
|
||||
|
||||
FuzzerCustomEventViewFieldEditorBack,
|
||||
FuzzerCustomEventViewFieldEditorOk,
|
||||
} FuzzerCustomEvent;
|
||||
30
applications/external/multi_fuzzer/helpers/fuzzer_types.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t menu_index;
|
||||
uint8_t proto_index;
|
||||
} FuzzerState;
|
||||
|
||||
typedef enum {
|
||||
FuzzerAttackStateOff = 0,
|
||||
FuzzerAttackStateIdle,
|
||||
FuzzerAttackStateRunning,
|
||||
FuzzerAttackStateEnd,
|
||||
|
||||
} FuzzerAttackState;
|
||||
|
||||
typedef enum {
|
||||
FuzzerFieldEditorStateEditingOn = 0,
|
||||
FuzzerFieldEditorStateEditingOff,
|
||||
|
||||
} FuzzerFieldEditorState;
|
||||
|
||||
typedef enum {
|
||||
FuzzerViewIDPopup,
|
||||
|
||||
FuzzerViewIDMain,
|
||||
FuzzerViewIDAttack,
|
||||
FuzzerViewIDFieldEditor,
|
||||
} FuzzerViewID;
|
||||
|
Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 308 B |
BIN
applications/external/multi_fuzzer/icons/ButtonLeft_4x7.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
applications/external/multi_fuzzer/icons/ButtonRight_4x7.png
vendored
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
applications/external/multi_fuzzer/icons/Ok_btn_9x9.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/external/multi_fuzzer/icons/Pin_arrow_up_7x9.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
applications/external/multi_fuzzer/icons/Pin_back_arrow_10x8.png
vendored
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
485
applications/external/multi_fuzzer/lib/worker/fake_worker.c
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
#include "fake_worker.h"
|
||||
#include "protocol_i.h"
|
||||
|
||||
#include <timer.h>
|
||||
|
||||
#include <lib/toolbox/hex.h>
|
||||
#include <toolbox/stream/stream.h>
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
|
||||
#define TAG "Fuzzer worker"
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
|
||||
#include <lib/lfrfid/lfrfid_dict_file.h>
|
||||
#include <lib/lfrfid/lfrfid_worker.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <lib/ibutton/ibutton_worker.h>
|
||||
#include <lib/ibutton/ibutton_key.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <toolbox/stream/stream.h>
|
||||
|
||||
struct FuzzerWorker {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
LFRFIDWorker* proto_worker;
|
||||
ProtocolId protocol_id;
|
||||
ProtocolDict* protocols_items;
|
||||
#else
|
||||
iButtonWorker* proto_worker;
|
||||
iButtonProtocolId protocol_id; // TODO
|
||||
iButtonProtocols* protocols_items;
|
||||
iButtonKey* key;
|
||||
#endif
|
||||
|
||||
const FuzzerProtocol* protocol;
|
||||
FuzzerWorkerAttackType attack_type;
|
||||
uint16_t timer_idle_time_ms;
|
||||
uint16_t timer_emu_time_ms;
|
||||
|
||||
uint8_t payload[MAX_PAYLOAD_SIZE];
|
||||
Stream* uids_stream;
|
||||
uint16_t index;
|
||||
uint8_t chusen_byte;
|
||||
|
||||
bool treead_running;
|
||||
bool in_emu_phase;
|
||||
FuriTimer* timer;
|
||||
|
||||
FuzzerWorkerUidChagedCallback tick_callback;
|
||||
void* tick_context;
|
||||
|
||||
FuzzerWorkerEndCallback end_callback;
|
||||
void* end_context;
|
||||
};
|
||||
|
||||
static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol);
|
||||
bool res = false;
|
||||
|
||||
const FuzzerProtocol* protocol = instance->protocol;
|
||||
|
||||
switch(instance->attack_type) {
|
||||
case FuzzerWorkerAttackTypeDefaultDict:
|
||||
if(next) {
|
||||
instance->index++;
|
||||
}
|
||||
if(instance->index < protocol->dict.len) {
|
||||
memcpy(
|
||||
instance->payload,
|
||||
&protocol->dict.val[instance->index * protocol->data_size],
|
||||
protocol->data_size);
|
||||
res = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case FuzzerWorkerAttackTypeLoadFileCustomUids: {
|
||||
if(next) {
|
||||
instance->index++;
|
||||
}
|
||||
uint8_t str_len = protocol->data_size * 2 + 1;
|
||||
FuriString* data_str = furi_string_alloc();
|
||||
while(true) {
|
||||
furi_string_reset(data_str);
|
||||
if(!stream_read_line(instance->uids_stream, data_str)) {
|
||||
stream_rewind(instance->uids_stream);
|
||||
// TODO Check empty file & close stream and storage
|
||||
break;
|
||||
} else if(furi_string_get_char(data_str, 0) == '#') {
|
||||
// Skip comment string
|
||||
continue;
|
||||
} else if(furi_string_size(data_str) != str_len) {
|
||||
// Ignore strin with bad length
|
||||
FURI_LOG_W(TAG, "Bad string length");
|
||||
continue;
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Uid candidate: \"%s\"", furi_string_get_cstr(data_str));
|
||||
bool parse_ok = true;
|
||||
for(uint8_t i = 0; i < protocol->data_size; i++) {
|
||||
if(!hex_char_to_uint8(
|
||||
furi_string_get_cstr(data_str)[i * 2],
|
||||
furi_string_get_cstr(data_str)[i * 2 + 1],
|
||||
&instance->payload[i])) {
|
||||
parse_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
res = parse_ok;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FuzzerWorkerAttackTypeLoadFile:
|
||||
if(instance->payload[instance->index] != 0xFF) {
|
||||
instance->payload[instance->index]++;
|
||||
res = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
protocol_dict_set_data(
|
||||
instance->protocols_items, instance->protocol_id, instance->payload, MAX_PAYLOAD_SIZE);
|
||||
#else
|
||||
ibutton_key_set_protocol_id(instance->key, instance->protocol_id);
|
||||
iButtonEditableData data;
|
||||
ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data);
|
||||
|
||||
// TODO check data.size logic
|
||||
data.size = MAX_PAYLOAD_SIZE;
|
||||
memcpy(data.ptr, instance->payload, MAX_PAYLOAD_SIZE); // data.size);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fuzzer_worker_on_tick_callback(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
FuzzerWorker* instance = context;
|
||||
|
||||
if(instance->in_emu_phase) {
|
||||
if(instance->treead_running) {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_stop(instance->proto_worker);
|
||||
#else
|
||||
ibutton_worker_stop(instance->proto_worker);
|
||||
#endif
|
||||
}
|
||||
instance->in_emu_phase = false;
|
||||
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_idle_time_ms));
|
||||
} else {
|
||||
if(!fuzzer_worker_load_key(instance, true)) {
|
||||
fuzzer_worker_pause(instance); // XXX
|
||||
if(instance->end_callback) {
|
||||
instance->end_callback(instance->end_context);
|
||||
}
|
||||
} else {
|
||||
if(instance->treead_running) {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id);
|
||||
#else
|
||||
ibutton_worker_emulate_start(instance->proto_worker, instance->key);
|
||||
#endif
|
||||
}
|
||||
instance->in_emu_phase = true;
|
||||
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
||||
if(instance->tick_callback) {
|
||||
instance->tick_callback(instance->tick_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output_key) {
|
||||
furi_assert(instance);
|
||||
furi_assert(output_key);
|
||||
furi_assert(instance->protocol);
|
||||
|
||||
output_key->data_size = instance->protocol->data_size;
|
||||
memcpy(output_key->data, instance->payload, instance->protocol->data_size);
|
||||
}
|
||||
|
||||
static void fuzzer_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
|
||||
instance->protocol = &fuzzer_proto_items[protocol_index];
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
instance->protocol_id =
|
||||
protocol_dict_get_protocol_by_name(instance->protocols_items, instance->protocol->name);
|
||||
#else
|
||||
// TODO iButtonProtocolIdInvalid check
|
||||
instance->protocol_id =
|
||||
ibutton_protocols_get_id_by_name(instance->protocols_items, instance->protocol->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fuzzer_worker_init_attack_dict(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool res = false;
|
||||
fuzzer_worker_set_protocol(instance, protocol_index);
|
||||
|
||||
instance->attack_type = FuzzerWorkerAttackTypeDefaultDict;
|
||||
instance->index = 0;
|
||||
|
||||
if(!fuzzer_worker_load_key(instance, false)) {
|
||||
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
||||
} else {
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool fuzzer_worker_init_attack_file_dict(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
FuriString* file_path) {
|
||||
furi_assert(instance);
|
||||
furi_assert(file_path);
|
||||
|
||||
bool res = false;
|
||||
fuzzer_worker_set_protocol(instance, protocol_index);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
instance->uids_stream = buffered_file_stream_alloc(storage);
|
||||
|
||||
if(!buffered_file_stream_open(
|
||||
instance->uids_stream, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
buffered_file_stream_close(instance->uids_stream);
|
||||
return res;
|
||||
}
|
||||
|
||||
instance->attack_type = FuzzerWorkerAttackTypeLoadFileCustomUids;
|
||||
instance->index = 0;
|
||||
|
||||
if(!fuzzer_worker_load_key(instance, false)) {
|
||||
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
||||
buffered_file_stream_close(instance->uids_stream);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
} else {
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool fuzzer_worker_init_attack_bf_byte(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
const FuzzerPayload* new_uid,
|
||||
uint8_t chusen) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool res = false;
|
||||
fuzzer_worker_set_protocol(instance, protocol_index);
|
||||
|
||||
instance->attack_type = FuzzerWorkerAttackTypeLoadFile;
|
||||
instance->index = chusen;
|
||||
|
||||
memcpy(instance->payload, new_uid->data, instance->protocol->data_size);
|
||||
|
||||
res = true;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO make it protocol independent
|
||||
bool fuzzer_worker_load_key_from_file(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
const char* filename) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool res = false;
|
||||
fuzzer_worker_set_protocol(instance, protocol_index);
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
ProtocolId loaded_proto_id = lfrfid_dict_file_load(instance->protocols_items, filename);
|
||||
if(loaded_proto_id == PROTOCOL_NO) {
|
||||
// Err Cant load file
|
||||
FURI_LOG_W(TAG, "Cant load file");
|
||||
} else if(instance->protocol_id != loaded_proto_id) { // Err wrong protocol
|
||||
FURI_LOG_W(TAG, "Wrong protocol");
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Selected: %s Loaded: %s",
|
||||
instance->protocol->name,
|
||||
protocol_dict_get_name(instance->protocols_items, loaded_proto_id));
|
||||
} else {
|
||||
protocol_dict_get_data(
|
||||
instance->protocols_items, instance->protocol_id, instance->payload, MAX_PAYLOAD_SIZE);
|
||||
res = true;
|
||||
}
|
||||
#else
|
||||
if(!ibutton_protocols_load(instance->protocols_items, instance->key, filename)) {
|
||||
// Err Cant load file
|
||||
FURI_LOG_W(TAG, "Cant load file");
|
||||
} else {
|
||||
if(instance->protocol_id != ibutton_key_get_protocol_id(instance->key)) {
|
||||
// Err wrong protocol
|
||||
FURI_LOG_W(TAG, "Wrong protocol");
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Selected: %s Loaded: %s",
|
||||
instance->protocol->name,
|
||||
ibutton_protocols_get_name(
|
||||
instance->protocols_items, ibutton_key_get_protocol_id(instance->key)));
|
||||
} else {
|
||||
iButtonEditableData data;
|
||||
ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data);
|
||||
memcpy(instance->payload, data.ptr, data.size);
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
FuzzerWorker* fuzzer_worker_alloc() {
|
||||
FuzzerWorker* instance = malloc(sizeof(FuzzerWorker));
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
instance->protocols_items = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
|
||||
instance->proto_worker = lfrfid_worker_alloc(instance->protocols_items);
|
||||
#else
|
||||
instance->protocols_items = ibutton_protocols_alloc();
|
||||
instance->key =
|
||||
ibutton_key_alloc(ibutton_protocols_get_max_data_size(instance->protocols_items));
|
||||
|
||||
instance->proto_worker = ibutton_worker_alloc(instance->protocols_items);
|
||||
#endif
|
||||
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
||||
instance->index = 0;
|
||||
instance->treead_running = false;
|
||||
instance->in_emu_phase = false;
|
||||
|
||||
memset(instance->payload, 0x00, sizeof(instance->payload));
|
||||
|
||||
instance->timer_idle_time_ms = PROTOCOL_DEF_IDLE_TIME * 100;
|
||||
instance->timer_emu_time_ms = PROTOCOL_DEF_EMU_TIME * 100;
|
||||
|
||||
instance->timer =
|
||||
furi_timer_alloc(fuzzer_worker_on_tick_callback, FuriTimerTypeOnce, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void fuzzer_worker_free(FuzzerWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
fuzzer_worker_stop(instance);
|
||||
|
||||
furi_timer_free(instance->timer);
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_free(instance->proto_worker);
|
||||
|
||||
protocol_dict_free(instance->protocols_items);
|
||||
#else
|
||||
ibutton_worker_free(instance->proto_worker);
|
||||
|
||||
ibutton_key_free(instance->key);
|
||||
ibutton_protocols_free(instance->protocols_items);
|
||||
#endif
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_time) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->attack_type < FuzzerWorkerAttackTypeMax) {
|
||||
if(idle_time == 0) {
|
||||
instance->timer_idle_time_ms = 10;
|
||||
} else {
|
||||
instance->timer_idle_time_ms = idle_time * 100;
|
||||
}
|
||||
if(emu_time == 0) {
|
||||
instance->timer_emu_time_ms = 10;
|
||||
} else {
|
||||
instance->timer_emu_time_ms = emu_time * 100;
|
||||
}
|
||||
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Emu_time %u ms Idle_time %u ms",
|
||||
instance->timer_emu_time_ms,
|
||||
instance->timer_idle_time_ms);
|
||||
|
||||
if(!instance->treead_running) {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_start_thread(instance->proto_worker);
|
||||
#else
|
||||
ibutton_worker_start_thread(instance->proto_worker);
|
||||
#endif
|
||||
FURI_LOG_D(TAG, "Worker Starting");
|
||||
instance->treead_running = true;
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Worker UnPaused");
|
||||
}
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
// lfrfid_worker_start_thread(instance->proto_worker);
|
||||
lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id);
|
||||
#else
|
||||
// ibutton_worker_start_thread(instance->proto_worker);
|
||||
ibutton_worker_emulate_start(instance->proto_worker, instance->key);
|
||||
#endif
|
||||
instance->in_emu_phase = true;
|
||||
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void fuzzer_worker_pause(FuzzerWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
furi_timer_stop(instance->timer);
|
||||
|
||||
if(instance->treead_running) {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_stop(instance->proto_worker);
|
||||
#else
|
||||
ibutton_worker_stop(instance->proto_worker);
|
||||
#endif
|
||||
FURI_LOG_D(TAG, "Worker Paused");
|
||||
}
|
||||
}
|
||||
|
||||
void fuzzer_worker_stop(FuzzerWorker* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
furi_timer_stop(instance->timer);
|
||||
|
||||
if(instance->treead_running) {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
lfrfid_worker_stop(instance->proto_worker);
|
||||
lfrfid_worker_stop_thread(instance->proto_worker);
|
||||
#else
|
||||
ibutton_worker_stop(instance->proto_worker);
|
||||
ibutton_worker_stop_thread(instance->proto_worker);
|
||||
#endif
|
||||
FURI_LOG_D(TAG, "Worker Stopping");
|
||||
instance->treead_running = false;
|
||||
}
|
||||
|
||||
if(instance->attack_type == FuzzerWorkerAttackTypeLoadFileCustomUids) {
|
||||
buffered_file_stream_close(instance->uids_stream);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
||||
}
|
||||
|
||||
// TODO anything else
|
||||
}
|
||||
|
||||
void fuzzer_worker_set_uid_chaged_callback(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerWorkerUidChagedCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
instance->tick_callback = callback;
|
||||
instance->tick_context = context;
|
||||
}
|
||||
|
||||
void fuzzer_worker_set_end_callback(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerWorkerEndCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
instance->end_callback = callback;
|
||||
instance->end_context = context;
|
||||
}
|
||||
138
applications/external/multi_fuzzer/lib/worker/fake_worker.h
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
typedef enum {
|
||||
FuzzerWorkerAttackTypeDefaultDict = 0,
|
||||
FuzzerWorkerAttackTypeLoadFile,
|
||||
FuzzerWorkerAttackTypeLoadFileCustomUids,
|
||||
|
||||
FuzzerWorkerAttackTypeMax,
|
||||
} FuzzerWorkerAttackType;
|
||||
|
||||
typedef void (*FuzzerWorkerUidChagedCallback)(void* context);
|
||||
typedef void (*FuzzerWorkerEndCallback)(void* context);
|
||||
|
||||
typedef struct FuzzerWorker FuzzerWorker;
|
||||
|
||||
/**
|
||||
* Allocate FuzzerWorker
|
||||
*
|
||||
* @return FuzzerWorker* pointer to FuzzerWorker
|
||||
*/
|
||||
FuzzerWorker* fuzzer_worker_alloc();
|
||||
|
||||
/**
|
||||
* Free FuzzerWorker
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
*/
|
||||
void fuzzer_worker_free(FuzzerWorker* instance);
|
||||
|
||||
/**
|
||||
* Start or continue emulation
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param idle_time Delay between emulations in tenths of a second
|
||||
* @param emu_time Emulation time of one UID in tenths of a second
|
||||
* @return bool True if emulation has started
|
||||
*/
|
||||
bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_time);
|
||||
|
||||
/**
|
||||
* Stop emulation and deinit worker
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
*/
|
||||
void fuzzer_worker_stop(FuzzerWorker* instance);
|
||||
|
||||
/**
|
||||
* Suspend emulation
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
*/
|
||||
void fuzzer_worker_pause(FuzzerWorker* instance);
|
||||
|
||||
/**
|
||||
* Init attack by default dictionary
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param protocol_index index of the selected protocol
|
||||
* @return bool True if initialization is successful
|
||||
*/
|
||||
bool fuzzer_worker_init_attack_dict(FuzzerWorker* instance, FuzzerProtocolsID protocol_index);
|
||||
|
||||
/**
|
||||
* Init attack by custom dictionary
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param protocol_index index of the selected protocol
|
||||
* @param file_path file path to the dictionary
|
||||
* @return bool True if initialization is successful
|
||||
*/
|
||||
bool fuzzer_worker_init_attack_file_dict(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
FuriString* file_path);
|
||||
|
||||
/**
|
||||
* Init attack brute force one of byte
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param protocol_index index of the selected protocol
|
||||
* @param new_uid Pointer to a FuzzerPayload with UID for brute force
|
||||
* @param chosen index of chusen byte
|
||||
* @return bool True if initialization is successful
|
||||
*/
|
||||
bool fuzzer_worker_init_attack_bf_byte(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
const FuzzerPayload* new_uid,
|
||||
uint8_t chusen);
|
||||
|
||||
/**
|
||||
* Get current UID
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param output_key Pointer to a FuzzerPayload
|
||||
*/
|
||||
void fuzzer_worker_get_current_key(FuzzerWorker* instance, FuzzerPayload* output_key);
|
||||
|
||||
/**
|
||||
* Load UID from Flipper Format Key file
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param protocol_index index of the selected protocol
|
||||
* @param filename file path to the key file
|
||||
* @return bool True if loading is successful
|
||||
*/
|
||||
bool fuzzer_worker_load_key_from_file(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerProtocolsID protocol_index,
|
||||
const char* filename);
|
||||
|
||||
/**
|
||||
* Set callback for uid changed
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param callback Callback for uid changed
|
||||
* @param context Context for callback
|
||||
*/
|
||||
void fuzzer_worker_set_uid_chaged_callback(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerWorkerUidChagedCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Set callback for end of emulation
|
||||
*
|
||||
* @param instance Pointer to a FuzzerWorker
|
||||
* @param callback Callback for end of emulation
|
||||
* @param context Context for callback
|
||||
*/
|
||||
void fuzzer_worker_set_end_callback(
|
||||
FuzzerWorker* instance,
|
||||
FuzzerWorkerEndCallback callback,
|
||||
void* context);
|
||||
291
applications/external/multi_fuzzer/lib/worker/protocol.c
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
#include "protocol_i.h"
|
||||
#include "furi.h"
|
||||
|
||||
// #######################
|
||||
// ## Ibutton Protocols ##
|
||||
// #######################
|
||||
#define DS1990_DATA_SIZE (8)
|
||||
#define Metakom_DATA_SIZE (4)
|
||||
#define Cyfral_DATA_SIZE (2)
|
||||
|
||||
const uint8_t uid_list_ds1990[][DS1990_DATA_SIZE] = {
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x5A, 0x36, 0x00, 0xE1}, //– код универсального ключа, для Vizit
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x5A, 0x56, 0x00, 0xBB}, //- проверен работает
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x00, 0x00, 0x00, 0x77}, //- проверен работает
|
||||
{0x01, 0xBE, 0x40, 0x11, 0x0A, 0x00, 0x00, 0x1D}, //- проверен работает Визит иногда КЕЙМАНЫ
|
||||
{0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F}, //- проверен(метаком, цифрал, ВИЗИТ).
|
||||
{0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x9B}, //- проверен Визит, Метакомы, КОНДОР
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14}, //???-Открываает 98% Метаком и некоторые Цифрал
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x19, 0xFF}, //???-Отлично работает на старых домофонах
|
||||
{0x01, 0x6F, 0x2E, 0x88, 0x8A, 0x00, 0x00, 0x4D}, //???-Открывать что-то должен
|
||||
{0x01, 0x53, 0xD4, 0xFE, 0x00, 0x00, 0x7E, 0x88}, //???-Cyfral, Metakom
|
||||
{0x01, 0x53, 0xD4, 0xFE, 0x00, 0x00, 0x00, 0x6F}, //???-домофоны Визит (Vizit) - до 99%
|
||||
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D}, //???-домофоны Cyfral CCD-20 - до 70%
|
||||
{0x01, 0x00, 0xBE, 0x11, 0xAA, 0x00, 0x00, 0xFB}, //???-домофоны Кейман (KEYMAN)
|
||||
{0x01, 0x76, 0xB8, 0x2E, 0x0F, 0x00, 0x00, 0x5C}, //???-домофоны Форвард
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14}, // Only FF
|
||||
{0x01, 0x78, 0x00, 0x48, 0xFD, 0xFF, 0xFF, 0xD1}, // StarNew Uni5
|
||||
{0x01, 0xA9, 0xE4, 0x3C, 0x09, 0x00, 0x00, 0xE6}, // Eltis Uni
|
||||
};
|
||||
|
||||
const uint8_t uid_list_metakom[][Metakom_DATA_SIZE] = {
|
||||
{0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d}, // ??
|
||||
{0x34, 0x00, 0x29, 0x3d}, // ??
|
||||
{0x04, 0xdf, 0x00, 0x00}, // ??
|
||||
{0xCA, 0xCA, 0xCA, 0xCA}, // ??
|
||||
};
|
||||
|
||||
const uint8_t uid_list_cyfral[][Cyfral_DATA_SIZE] = {
|
||||
{0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34}, // Incremental UID
|
||||
{0x56, 0x34}, // Decremental UID
|
||||
{0xCA, 0xCA}, // ??
|
||||
{0x8E, 0xC9}, // Elevator code
|
||||
{0x6A, 0x50}, // VERY fresh code from smartkey
|
||||
};
|
||||
|
||||
// ###########################
|
||||
// ## Rfid_125khz Protocols ##
|
||||
// ###########################
|
||||
#define EM4100_DATA_SIZE (5)
|
||||
#define HIDProx_DATA_SIZE (6)
|
||||
#define PAC_DATA_SIZE (4)
|
||||
#define H10301_DATA_SIZE (3)
|
||||
|
||||
const uint8_t uid_list_em4100[][EM4100_DATA_SIZE] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
const uint8_t uid_list_hid[][HIDProx_DATA_SIZE] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, // Incremental UID
|
||||
{0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
const uint8_t uid_list_pac[][PAC_DATA_SIZE] = {
|
||||
{0x00, 0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56, 0x78}, // Incremental UID
|
||||
{0x9A, 0x78, 0x56, 0x34}, // Decremental UID
|
||||
{0x04, 0xd0, 0x9b, 0x0d}, // From arha
|
||||
{0x34, 0x00, 0x29, 0x3d}, // From arha
|
||||
{0x04, 0xdf, 0x00, 0x00}, // From arha
|
||||
{0xCA, 0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
const uint8_t uid_list_h10301[][H10301_DATA_SIZE] = {
|
||||
{0x00, 0x00, 0x00}, // Null bytes
|
||||
{0xFF, 0xFF, 0xFF}, // Only FF
|
||||
{0x11, 0x11, 0x11}, // Only 11
|
||||
{0x22, 0x22, 0x22}, // Only 22
|
||||
{0x33, 0x33, 0x33}, // Only 33
|
||||
{0x44, 0x44, 0x44}, // Only 44
|
||||
{0x55, 0x55, 0x55}, // Only 55
|
||||
{0x66, 0x66, 0x66}, // Only 66
|
||||
{0x77, 0x77, 0x77}, // Only 77
|
||||
{0x88, 0x88, 0x88}, // Only 88
|
||||
{0x99, 0x99, 0x99}, // Only 99
|
||||
{0x12, 0x34, 0x56}, // Incremental UID
|
||||
{0x56, 0x34, 0x12}, // Decremental UID
|
||||
{0xCA, 0xCA, 0xCA}, // From arha
|
||||
};
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
const FuzzerProtocol fuzzer_proto_items[] = {
|
||||
[EM4100] =
|
||||
{
|
||||
.name = "EM4100",
|
||||
.data_size = EM4100_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_em4100,
|
||||
.len = COUNT_OF(uid_list_em4100),
|
||||
},
|
||||
},
|
||||
[HIDProx] =
|
||||
{
|
||||
.name = "HIDProx",
|
||||
.data_size = HIDProx_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_hid,
|
||||
.len = COUNT_OF(uid_list_hid),
|
||||
},
|
||||
},
|
||||
[PAC] =
|
||||
{
|
||||
.name = "PAC/Stanley",
|
||||
.data_size = PAC_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_pac,
|
||||
.len = COUNT_OF(uid_list_pac),
|
||||
},
|
||||
},
|
||||
[H10301] =
|
||||
{
|
||||
.name = "H10301",
|
||||
.data_size = H10301_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_h10301,
|
||||
.len = COUNT_OF(uid_list_h10301),
|
||||
},
|
||||
},
|
||||
};
|
||||
#else
|
||||
const FuzzerProtocol fuzzer_proto_items[] = {
|
||||
[DS1990] =
|
||||
{
|
||||
.name = "DS1990",
|
||||
.data_size = DS1990_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_ds1990,
|
||||
.len = COUNT_OF(uid_list_ds1990),
|
||||
},
|
||||
},
|
||||
[Metakom] =
|
||||
{
|
||||
.name = "Metakom",
|
||||
.data_size = Metakom_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_metakom,
|
||||
.len = COUNT_OF(uid_list_metakom),
|
||||
},
|
||||
},
|
||||
[Cyfral] =
|
||||
{
|
||||
.name = "Cyfral",
|
||||
.data_size = Cyfral_DATA_SIZE,
|
||||
.dict =
|
||||
{
|
||||
.val = (const uint8_t*)&uid_list_cyfral,
|
||||
.len = COUNT_OF(uid_list_cyfral),
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char* menu_label;
|
||||
FuzzerAttackId attack_id;
|
||||
} FuzzerMenuItems;
|
||||
|
||||
const FuzzerMenuItems fuzzer_menu_items[] = {
|
||||
{"Default Values", FuzzerAttackIdDefaultValues},
|
||||
#ifdef RFID_125_PROTOCOL
|
||||
{"BF Customer ID", FuzzerAttackIdBFCustomerID},
|
||||
#endif
|
||||
{"Load File", FuzzerAttackIdLoadFile},
|
||||
{"Load UIDs from file", FuzzerAttackIdLoadFileCustomUids},
|
||||
};
|
||||
|
||||
FuzzerPayload* fuzzer_payload_alloc() {
|
||||
FuzzerPayload* payload = malloc(sizeof(FuzzerPayload));
|
||||
payload->data = malloc(sizeof(payload->data[0]) * MAX_PAYLOAD_SIZE);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
void fuzzer_payload_free(FuzzerPayload* payload) {
|
||||
furi_assert(payload);
|
||||
|
||||
if(payload->data) {
|
||||
free(payload->data);
|
||||
}
|
||||
free(payload);
|
||||
}
|
||||
|
||||
const char* fuzzer_proto_get_name(FuzzerProtocolsID index) {
|
||||
return fuzzer_proto_items[index].name;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_proto_get_count_of_protocols() {
|
||||
return COUNT_OF(fuzzer_proto_items);
|
||||
}
|
||||
|
||||
uint8_t fuzzer_proto_get_max_data_size() {
|
||||
return MAX_PAYLOAD_SIZE;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_proto_get_def_emu_time() {
|
||||
return PROTOCOL_DEF_EMU_TIME;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_proto_get_def_idle_time() {
|
||||
return PROTOCOL_DEF_IDLE_TIME;
|
||||
}
|
||||
|
||||
const char* fuzzer_proto_get_menu_label(uint8_t index) {
|
||||
return fuzzer_menu_items[index].menu_label;
|
||||
}
|
||||
|
||||
FuzzerAttackId fuzzer_proto_get_attack_id_by_index(uint8_t index) {
|
||||
return fuzzer_menu_items[index].attack_id;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_proto_get_count_of_menu_items() {
|
||||
return COUNT_OF(fuzzer_menu_items);
|
||||
}
|
||||
89
applications/external/multi_fuzzer/lib/worker/protocol.h
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// #define RFID_125_PROTOCOL
|
||||
|
||||
typedef struct FuzzerPayload FuzzerPayload;
|
||||
|
||||
typedef enum {
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
EM4100,
|
||||
HIDProx,
|
||||
PAC,
|
||||
H10301,
|
||||
#else
|
||||
DS1990,
|
||||
Metakom,
|
||||
Cyfral,
|
||||
#endif
|
||||
} FuzzerProtocolsID;
|
||||
|
||||
typedef enum {
|
||||
FuzzerAttackIdDefaultValues = 0,
|
||||
FuzzerAttackIdLoadFile,
|
||||
FuzzerAttackIdLoadFileCustomUids,
|
||||
FuzzerAttackIdBFCustomerID,
|
||||
} FuzzerAttackId;
|
||||
|
||||
struct FuzzerPayload {
|
||||
uint8_t* data;
|
||||
uint8_t data_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allocate FuzzerPayload
|
||||
*
|
||||
* @return FuzzerPayload* pointer to FuzzerPayload
|
||||
*/
|
||||
FuzzerPayload* fuzzer_payload_alloc();
|
||||
|
||||
/**
|
||||
* Free FuzzerPayload
|
||||
*
|
||||
* @param instance Pointer to a FuzzerPayload
|
||||
*/
|
||||
void fuzzer_payload_free(FuzzerPayload*);
|
||||
|
||||
/**
|
||||
* Get maximum length of UID among all supported protocols
|
||||
* @return Maximum length of UID
|
||||
*/
|
||||
uint8_t fuzzer_proto_get_max_data_size();
|
||||
|
||||
// TODO add description
|
||||
uint8_t fuzzer_proto_get_def_emu_time();
|
||||
uint8_t fuzzer_proto_get_def_idle_time();
|
||||
|
||||
/**
|
||||
* Get protocol name based on its index
|
||||
* @param index protocol index
|
||||
* @return pointer to a string containing the name
|
||||
*/
|
||||
const char* fuzzer_proto_get_name(FuzzerProtocolsID index);
|
||||
|
||||
/**
|
||||
* Get number of protocols
|
||||
* @return number of protocols
|
||||
*/
|
||||
uint8_t fuzzer_proto_get_count_of_protocols();
|
||||
|
||||
/**
|
||||
* Get menu label based on its index
|
||||
* @param index menu index
|
||||
* @return pointer to a string containing the menu label
|
||||
*/
|
||||
const char* fuzzer_proto_get_menu_label(uint8_t index);
|
||||
|
||||
/**
|
||||
* Get FuzzerAttackId based on its index
|
||||
* @param index menu index
|
||||
* @return FuzzerAttackId
|
||||
*/
|
||||
FuzzerAttackId fuzzer_proto_get_attack_id_by_index(uint8_t index);
|
||||
|
||||
/**
|
||||
* Get number of menu items
|
||||
* @return number of menu items
|
||||
*/
|
||||
uint8_t fuzzer_proto_get_count_of_menu_items();
|
||||
43
applications/external/multi_fuzzer/lib/worker/protocol_i.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
#if defined(RFID_125_PROTOCOL)
|
||||
#define MAX_PAYLOAD_SIZE (6)
|
||||
#define PROTOCOL_DEF_IDLE_TIME (4)
|
||||
#define PROTOCOL_DEF_EMU_TIME (5)
|
||||
#define PROTOCOL_TIME_DELAY_MIN PROTOCOL_DEF_IDLE_TIME + PROTOCOL_DEF_EMU_TIME
|
||||
#else
|
||||
#define MAX_PAYLOAD_SIZE (8)
|
||||
#define PROTOCOL_DEF_IDLE_TIME (2)
|
||||
#define PROTOCOL_DEF_EMU_TIME (2)
|
||||
#define PROTOCOL_TIME_DELAY_MIN PROTOCOL_DEF_IDLE_TIME + PROTOCOL_DEF_EMU_TIME
|
||||
#endif
|
||||
|
||||
typedef struct ProtoDict ProtoDict;
|
||||
typedef struct FuzzerProtocol FuzzerProtocol;
|
||||
|
||||
struct ProtoDict {
|
||||
const uint8_t* val;
|
||||
const uint8_t len;
|
||||
};
|
||||
|
||||
struct FuzzerProtocol {
|
||||
const char* name;
|
||||
const uint8_t data_size;
|
||||
const ProtoDict dict;
|
||||
};
|
||||
|
||||
// #define MAX_PAYLOAD_SIZE 6
|
||||
|
||||
// #define FUZZ_TIME_DELAY_MIN (5)
|
||||
// #define FUZZ_TIME_DELAY_DEFAULT (10)
|
||||
// #define FUZZ_TIME_DELAY_MAX (70)
|
||||
|
||||
// #define MAX_PAYLOAD_SIZE 8
|
||||
|
||||
// #define FUZZ_TIME_DELAY_MIN (4)
|
||||
// #define FUZZ_TIME_DELAY_DEFAULT (8)
|
||||
// #define FUZZ_TIME_DELAY_MAX (80)
|
||||
|
||||
extern const FuzzerProtocol fuzzer_proto_items[];
|
||||
30
applications/external/multi_fuzzer/scenes/fuzzer_scene.c
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "fuzzer_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const fuzzer_scene_on_enter_handlers[])(void*) = {
|
||||
#include "fuzzer_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const fuzzer_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "fuzzer_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const fuzzer_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "fuzzer_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers fuzzer_scene_handlers = {
|
||||
.on_enter_handlers = fuzzer_scene_on_enter_handlers,
|
||||
.on_event_handlers = fuzzer_scene_on_event_handlers,
|
||||
.on_exit_handlers = fuzzer_scene_on_exit_handlers,
|
||||
.scene_num = FuzzerSceneNum,
|
||||
};
|
||||
29
applications/external/multi_fuzzer/scenes/fuzzer_scene.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) FuzzerScene##id,
|
||||
typedef enum {
|
||||
#include "fuzzer_scene_config.h"
|
||||
FuzzerSceneNum,
|
||||
} FuzzerScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers fuzzer_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "fuzzer_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "fuzzer_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "fuzzer_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
162
applications/external/multi_fuzzer/scenes/fuzzer_scene_attack.c
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "../fuzzer_i.h"
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
|
||||
const NotificationSequence sequence_one_green_50_on_blink_blue = {
|
||||
&message_red_255,
|
||||
&message_delay_50,
|
||||
&message_red_0,
|
||||
&message_blink_start_10,
|
||||
&message_blink_set_color_blue,
|
||||
&message_do_not_reset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void fuzzer_scene_attack_update_uid(PacsFuzzerApp* app) {
|
||||
furi_assert(app);
|
||||
furi_assert(app->worker);
|
||||
furi_assert(app->attack_view);
|
||||
|
||||
fuzzer_worker_get_current_key(app->worker, app->payload);
|
||||
|
||||
fuzzer_view_attack_set_uid(app->attack_view, app->payload);
|
||||
}
|
||||
|
||||
static void fuzzer_scene_attack_set_state(PacsFuzzerApp* app, FuzzerAttackState state) {
|
||||
furi_assert(app);
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, FuzzerSceneAttack, state);
|
||||
switch(state) {
|
||||
case FuzzerAttackStateIdle:
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
fuzzer_view_attack_pause(app->attack_view);
|
||||
break;
|
||||
|
||||
case FuzzerAttackStateRunning:
|
||||
notification_message(app->notifications, &sequence_blink_start_blue);
|
||||
fuzzer_view_attack_start(app->attack_view);
|
||||
break;
|
||||
|
||||
case FuzzerAttackStateEnd:
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
notification_message(app->notifications, &sequence_single_vibro);
|
||||
fuzzer_view_attack_end(app->attack_view);
|
||||
break;
|
||||
|
||||
case FuzzerAttackStateOff:
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
fuzzer_view_attack_stop(app->attack_view);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fuzzer_scene_attack_worker_tick_callback(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
notification_message(app->notifications, &sequence_one_green_50_on_blink_blue);
|
||||
fuzzer_scene_attack_update_uid(app);
|
||||
|
||||
// view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventViewAttackTick);
|
||||
}
|
||||
|
||||
void fuzzer_scene_attack_worker_end_callback(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventViewAttackEnd);
|
||||
}
|
||||
|
||||
void fuzzer_scene_attack_callback(FuzzerCustomEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void fuzzer_scene_attack_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
fuzzer_view_attack_set_callback(app->attack_view, fuzzer_scene_attack_callback, app);
|
||||
|
||||
fuzzer_worker_set_uid_chaged_callback(
|
||||
app->worker, fuzzer_scene_attack_worker_tick_callback, app);
|
||||
|
||||
fuzzer_worker_set_end_callback(app->worker, fuzzer_scene_attack_worker_end_callback, app);
|
||||
|
||||
fuzzer_view_attack_reset_data(
|
||||
app->attack_view,
|
||||
fuzzer_proto_get_menu_label(app->fuzzer_state.menu_index),
|
||||
fuzzer_proto_get_name(app->fuzzer_state.proto_index));
|
||||
|
||||
fuzzer_scene_attack_update_uid(app);
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, FuzzerSceneAttack, FuzzerAttackStateIdle);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDAttack);
|
||||
}
|
||||
|
||||
bool fuzzer_scene_attack_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == FuzzerCustomEventViewAttackBack) {
|
||||
if(scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) ==
|
||||
FuzzerAttackStateRunning) {
|
||||
// Pause if attack running
|
||||
fuzzer_worker_pause(app->worker);
|
||||
|
||||
fuzzer_scene_attack_set_state(app, FuzzerAttackStateIdle);
|
||||
} else {
|
||||
// Exit
|
||||
fuzzer_worker_stop(app->worker);
|
||||
|
||||
fuzzer_scene_attack_set_state(app, FuzzerAttackStateOff);
|
||||
if(!scene_manager_previous_scene(app->scene_manager)) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == FuzzerCustomEventViewAttackOk) {
|
||||
if(scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) ==
|
||||
FuzzerAttackStateIdle) {
|
||||
// Start or Continue Attack
|
||||
if(fuzzer_worker_start(
|
||||
app->worker,
|
||||
fuzzer_view_attack_get_time_delay(app->attack_view),
|
||||
fuzzer_view_attack_get_emu_time(app->attack_view))) {
|
||||
fuzzer_scene_attack_set_state(app, FuzzerAttackStateRunning);
|
||||
} else {
|
||||
// Error?
|
||||
}
|
||||
} else if(
|
||||
scene_manager_get_scene_state(app->scene_manager, FuzzerSceneAttack) ==
|
||||
FuzzerAttackStateRunning) {
|
||||
// Pause if attack running
|
||||
fuzzer_worker_pause(app->worker);
|
||||
|
||||
fuzzer_scene_attack_set_state(app, FuzzerAttackStateIdle);
|
||||
}
|
||||
consumed = true;
|
||||
// } else if(event.event == FuzzerCustomEventViewAttackTick) {
|
||||
// consumed = true;
|
||||
} else if(event.event == FuzzerCustomEventViewAttackEnd) {
|
||||
fuzzer_scene_attack_set_state(app, FuzzerAttackStateEnd);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void fuzzer_scene_attack_on_exit(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
// XXX the scene has no descendants, and the return will be processed in on_event
|
||||
// fuzzer_worker_stop();
|
||||
|
||||
fuzzer_worker_set_uid_chaged_callback(app->worker, NULL, NULL);
|
||||
fuzzer_worker_set_end_callback(app->worker, NULL, NULL);
|
||||
}
|
||||
3
applications/external/multi_fuzzer/scenes/fuzzer_scene_config.h
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
ADD_SCENE(fuzzer, main, Main)
|
||||
ADD_SCENE(fuzzer, attack, Attack)
|
||||
ADD_SCENE(fuzzer, field_editor, FieldEditor)
|
||||
66
applications/external/multi_fuzzer/scenes/fuzzer_scene_field_editor.c
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "../fuzzer_i.h"
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
|
||||
void fuzzer_scene_field_editor_callback(FuzzerCustomEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void fuzzer_scene_field_editor_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
fuzzer_view_field_editor_set_callback(
|
||||
app->field_editor_view, fuzzer_scene_field_editor_callback, app);
|
||||
|
||||
fuzzer_worker_get_current_key(app->worker, app->payload);
|
||||
|
||||
switch(scene_manager_get_scene_state(app->scene_manager, FuzzerSceneFieldEditor)) {
|
||||
case FuzzerFieldEditorStateEditingOn:
|
||||
fuzzer_view_field_editor_reset_data(app->field_editor_view, app->payload, true);
|
||||
break;
|
||||
|
||||
case FuzzerFieldEditorStateEditingOff:
|
||||
fuzzer_view_field_editor_reset_data(app->field_editor_view, app->payload, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDFieldEditor);
|
||||
}
|
||||
|
||||
bool fuzzer_scene_field_editor_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == FuzzerCustomEventViewFieldEditorBack) {
|
||||
if(!scene_manager_previous_scene(app->scene_manager)) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == FuzzerCustomEventViewFieldEditorOk) {
|
||||
fuzzer_view_field_editor_get_uid(app->field_editor_view, app->payload);
|
||||
if(fuzzer_worker_init_attack_bf_byte(
|
||||
app->worker,
|
||||
app->fuzzer_state.proto_index,
|
||||
app->payload,
|
||||
fuzzer_view_field_editor_get_index(app->field_editor_view))) {
|
||||
scene_manager_next_scene(app->scene_manager, FuzzerSceneAttack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void fuzzer_scene_field_editor_on_exit(void* context) {
|
||||
// furi_assert(context);
|
||||
// PacsFuzzerApp* app = context;
|
||||
UNUSED(context);
|
||||
}
|
||||
189
applications/external/multi_fuzzer/scenes/fuzzer_scene_main.c
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "../fuzzer_i.h"
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
|
||||
#include "../lib/worker/protocol.h"
|
||||
|
||||
void fuzzer_scene_main_callback(FuzzerCustomEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void fuzzer_scene_main_error_popup_callback(void* context) {
|
||||
PacsFuzzerApp* app = context;
|
||||
notification_message(app->notifications, &sequence_reset_rgb);
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, FuzzerCustomEventViewMainPopupErr);
|
||||
}
|
||||
|
||||
static bool fuzzer_scene_main_load_custom_dict(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
FuzzerConsts* consts = app->fuzzer_const;
|
||||
|
||||
furi_string_set_str(app->file_path, consts->custom_dict_folder);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, consts->custom_dict_extension, &I_rfid_10px);
|
||||
browser_options.base_path = consts->custom_dict_folder;
|
||||
browser_options.hide_ext = false;
|
||||
|
||||
bool res =
|
||||
dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool fuzzer_scene_main_load_key(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
FuzzerConsts* consts = app->fuzzer_const;
|
||||
|
||||
furi_string_set_str(app->file_path, consts->path_key_folder);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, consts->key_extension, consts->key_icon);
|
||||
browser_options.base_path = consts->path_key_folder;
|
||||
browser_options.hide_ext = true;
|
||||
|
||||
bool res =
|
||||
dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void fuzzer_scene_main_show_error(void* context, const char* erre_str) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
popup_set_header(app->popup, erre_str, 64, 20, AlignCenter, AlignTop);
|
||||
notification_message(app->notifications, &sequence_set_red_255);
|
||||
notification_message(app->notifications, &sequence_double_vibro);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDPopup);
|
||||
}
|
||||
|
||||
void fuzzer_scene_main_on_enter(void* context) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
|
||||
fuzzer_view_main_set_callback(app->main_view, fuzzer_scene_main_callback, app);
|
||||
|
||||
fuzzer_view_main_update_data(app->main_view, app->fuzzer_state);
|
||||
|
||||
// Setup view
|
||||
Popup* popup = app->popup;
|
||||
// popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
popup_set_timeout(popup, 2500);
|
||||
popup_set_context(popup, app);
|
||||
popup_set_callback(popup, fuzzer_scene_main_error_popup_callback);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDMain);
|
||||
}
|
||||
|
||||
bool fuzzer_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_assert(context);
|
||||
PacsFuzzerApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == FuzzerCustomEventViewMainBack) {
|
||||
if(!scene_manager_previous_scene(app->scene_manager)) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == FuzzerCustomEventViewMainPopupErr) {
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, FuzzerViewIDMain);
|
||||
consumed = true;
|
||||
} else if(event.event == FuzzerCustomEventViewMainOk) {
|
||||
fuzzer_view_main_get_state(app->main_view, &app->fuzzer_state);
|
||||
|
||||
// TODO error logic
|
||||
bool loading_ok = false;
|
||||
|
||||
switch(fuzzer_proto_get_attack_id_by_index(app->fuzzer_state.menu_index)) {
|
||||
case FuzzerAttackIdDefaultValues:
|
||||
loading_ok =
|
||||
fuzzer_worker_init_attack_dict(app->worker, app->fuzzer_state.proto_index);
|
||||
|
||||
if(!loading_ok) {
|
||||
// error
|
||||
fuzzer_scene_main_show_error(app, "Default dictionary\nis empty");
|
||||
}
|
||||
break;
|
||||
|
||||
case FuzzerAttackIdBFCustomerID:
|
||||
// TODO
|
||||
app->payload->data_size = fuzzer_proto_get_max_data_size();
|
||||
memset(app->payload->data, 0x00, app->payload->data_size);
|
||||
|
||||
if(fuzzer_worker_init_attack_bf_byte(
|
||||
app->worker, app->fuzzer_state.proto_index, app->payload, 0)) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
FuzzerSceneFieldEditor,
|
||||
FuzzerFieldEditorStateEditingOff);
|
||||
scene_manager_next_scene(app->scene_manager, FuzzerSceneFieldEditor);
|
||||
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
break;
|
||||
|
||||
case FuzzerAttackIdLoadFile:
|
||||
if(!fuzzer_scene_main_load_key(app)) {
|
||||
break;
|
||||
} else {
|
||||
if(fuzzer_worker_load_key_from_file(
|
||||
app->worker,
|
||||
app->fuzzer_state.proto_index,
|
||||
furi_string_get_cstr(app->file_path))) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
FuzzerSceneFieldEditor,
|
||||
FuzzerFieldEditorStateEditingOn);
|
||||
scene_manager_next_scene(app->scene_manager, FuzzerSceneFieldEditor);
|
||||
FURI_LOG_I("Scene", "Load ok");
|
||||
} else {
|
||||
fuzzer_scene_main_show_error(app, "Unsupported protocol\nor broken file");
|
||||
FURI_LOG_W("Scene", "Load err");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FuzzerAttackIdLoadFileCustomUids:
|
||||
if(!fuzzer_scene_main_load_custom_dict(app)) {
|
||||
break;
|
||||
} else {
|
||||
loading_ok = fuzzer_worker_init_attack_file_dict(
|
||||
app->worker, app->fuzzer_state.proto_index, app->file_path);
|
||||
if(!loading_ok) {
|
||||
fuzzer_scene_main_show_error(app, "Incorrect key format\nor length");
|
||||
// error
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fuzzer_scene_main_show_error(app, "Unsuported attack");
|
||||
break;
|
||||
}
|
||||
|
||||
if(loading_ok) {
|
||||
scene_manager_next_scene(app->scene_manager, FuzzerSceneAttack);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void fuzzer_scene_main_on_exit(void* context) {
|
||||
// furi_assert(context);
|
||||
// PacsFuzzerApp* app = context;
|
||||
UNUSED(context);
|
||||
}
|
||||
44
applications/external/multi_fuzzer/todo.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
## Working Improvement
|
||||
|
||||
#### Quality of life
|
||||
|
||||
- [ ] Make the "Load File" independent of the current protocol
|
||||
- [x] Add pause
|
||||
- [ ] Switching UIDs if possible
|
||||
- [x] Led and sound Notification
|
||||
- [x] Led
|
||||
- [x] Vibro
|
||||
- [ ] Sound?
|
||||
- [x] Error Notification
|
||||
- [x] Custom UIDs dict loading
|
||||
- [x] Key file loading
|
||||
- [ ] Anything else
|
||||
|
||||
#### App functionality
|
||||
|
||||
- [x] Add `BFCustomerID` attack
|
||||
- [x] Add the ability to select index
|
||||
- [ ] Save key logic
|
||||
|
||||
## Code Improvement
|
||||
|
||||
- [ ] GUI
|
||||
- [x] Rewrite `gui_const` logic
|
||||
- [x] Icon in dialog
|
||||
- [x] Description and buttons in `field_editor` view
|
||||
- [ ] Protocol carousel in `main_menu`
|
||||
- [x] prototype
|
||||
- [x] Add the ability to edit emulation time and downtime separately
|
||||
- [x] Decide on the display
|
||||
- [x] UID
|
||||
- [x] Simplify the storage and exchange of `uids.data` `uid.data_size` in `views`
|
||||
- [x] Using `FuzzerPayload` to store the uid
|
||||
- [x] `UID_MAX_SIZE`
|
||||
- [x] Add pause
|
||||
- [x] Fix `Custom dict` attack when ended
|
||||
- [ ] Pause V2
|
||||
- [ ] Save logic
|
||||
- [ ] Switching UIDs if possible
|
||||
- [ ] Worker
|
||||
- [ ] Use `prtocol_id` instead of protocol name
|
||||
- [x] this can be simplified `fuzzer_proto_items`
|
||||
384
applications/external/multi_fuzzer/views/attack.c
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
#include "attack.h"
|
||||
#include "../fuzzer_i.h"
|
||||
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#define ATTACK_SCENE_MAX_UID_LENGTH 25
|
||||
#define UID_MAX_DISPLAYED_LEN (8U)
|
||||
#define LIFT_RIGHT_OFFSET (3)
|
||||
|
||||
struct FuzzerViewAttack {
|
||||
View* view;
|
||||
FuzzerViewAttackCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t time_delay; // 1 = 100ms
|
||||
uint8_t time_delay_min; // 1 = 100ms
|
||||
uint8_t emu_time; // 1 = 100ms
|
||||
uint8_t emu_time_min; // 1 = 100ms
|
||||
bool td_emt_cursor; // false - time_delay, true - emu_time
|
||||
const char* attack_name;
|
||||
const char* protocol_name;
|
||||
FuzzerAttackState attack_state;
|
||||
FuriString* uid_str;
|
||||
} FuzzerViewAttackModel;
|
||||
|
||||
void fuzzer_view_attack_reset_data(
|
||||
FuzzerViewAttack* view,
|
||||
const char* attack_name,
|
||||
const char* protocol_name) {
|
||||
furi_assert(view);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{
|
||||
model->attack_name = attack_name;
|
||||
model->protocol_name = protocol_name;
|
||||
model->attack_state = FuzzerAttackStateIdle;
|
||||
furi_string_set_str(model->uid_str, "Not_set");
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_set_uid(FuzzerViewAttack* view, const FuzzerPayload* uid) {
|
||||
furi_assert(view);
|
||||
furi_assert(uid->data);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{
|
||||
furi_string_printf(model->uid_str, "%02X", uid->data[0]);
|
||||
for(uint8_t i = 1; i < uid->data_size; i++) {
|
||||
furi_string_cat_printf(model->uid_str, ":%02X", uid->data[i]);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_start(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ model->attack_state = FuzzerAttackStateRunning; },
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_stop(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ model->attack_state = FuzzerAttackStateOff; },
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_pause(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ model->attack_state = FuzzerAttackStateIdle; },
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_end(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ model->attack_state = FuzzerAttackStateEnd; },
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_set_callback(
|
||||
FuzzerViewAttack* view_attack,
|
||||
FuzzerViewAttackCallback callback,
|
||||
void* context) {
|
||||
furi_assert(view_attack);
|
||||
|
||||
view_attack->callback = callback;
|
||||
view_attack->context = context;
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_draw(Canvas* canvas, FuzzerViewAttackModel* model) {
|
||||
char temp_str[50];
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, model->attack_name);
|
||||
|
||||
uint16_t crt;
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
if(!model->td_emt_cursor) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(temp_str, sizeof(temp_str), "Time delay:");
|
||||
canvas_draw_str_aligned(canvas, LIFT_RIGHT_OFFSET, 21, AlignLeft, AlignBottom, temp_str);
|
||||
crt = canvas_string_width(canvas, temp_str);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(
|
||||
temp_str, sizeof(temp_str), "%d.%d", model->time_delay / 10, model->time_delay % 10);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, crt + LIFT_RIGHT_OFFSET + 3, 21, AlignLeft, AlignBottom, temp_str);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(
|
||||
temp_str, sizeof(temp_str), "EmT: %d.%d", model->emu_time / 10, model->emu_time % 10);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 128 - LIFT_RIGHT_OFFSET, 21, AlignRight, AlignBottom, temp_str);
|
||||
} else {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(
|
||||
temp_str,
|
||||
sizeof(temp_str),
|
||||
"TD: %d.%d",
|
||||
model->time_delay / 10,
|
||||
model->time_delay % 10);
|
||||
|
||||
canvas_draw_str_aligned(canvas, LIFT_RIGHT_OFFSET, 21, AlignLeft, AlignBottom, temp_str);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(temp_str, sizeof(temp_str), "%d.%d", model->emu_time / 10, model->emu_time % 10);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 128 - LIFT_RIGHT_OFFSET, 21, AlignRight, AlignBottom, temp_str);
|
||||
crt = canvas_string_width(canvas, temp_str);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(temp_str, sizeof(temp_str), "Emulation time:");
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 128 - LIFT_RIGHT_OFFSET - crt - 3, 21, AlignRight, AlignBottom, temp_str);
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, model->protocol_name);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
if(128 < canvas_string_width(canvas, furi_string_get_cstr(model->uid_str))) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 38, AlignCenter, AlignTop, furi_string_get_cstr(model->uid_str));
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->attack_state == FuzzerAttackStateRunning) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->attack_state == FuzzerAttackStateIdle) {
|
||||
if(model->td_emt_cursor) {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_left(canvas, "EmT -");
|
||||
elements_button_right(canvas, "+ EmT");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_left(canvas, "TD -");
|
||||
elements_button_right(canvas, "+ TD");
|
||||
}
|
||||
|
||||
} else if(model->attack_state == FuzzerAttackStateEnd) {
|
||||
// elements_button_center(canvas, "Restart"); // Reset
|
||||
elements_button_left(canvas, "Exit");
|
||||
}
|
||||
}
|
||||
|
||||
bool fuzzer_view_attack_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
FuzzerViewAttack* view_attack = context;
|
||||
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
view_attack->callback(FuzzerCustomEventViewAttackOk, view_attack->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
with_view_model(
|
||||
view_attack->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{
|
||||
if(model->attack_state == FuzzerAttackStateIdle) {
|
||||
if(!model->td_emt_cursor) {
|
||||
// TimeDelay --
|
||||
if(event->type == InputTypeShort) {
|
||||
if(model->time_delay > model->time_delay_min) {
|
||||
model->time_delay--;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
if((model->time_delay - 10) >= model->time_delay_min) {
|
||||
model->time_delay -= 10;
|
||||
} else {
|
||||
model->time_delay = model->time_delay_min;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// EmuTime --
|
||||
if(event->type == InputTypeShort) {
|
||||
if(model->emu_time > model->emu_time_min) {
|
||||
model->emu_time--;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
if((model->emu_time - 10) >= model->emu_time_min) {
|
||||
model->emu_time -= 10;
|
||||
} else {
|
||||
model->emu_time = model->emu_time_min;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(
|
||||
(model->attack_state == FuzzerAttackStateEnd) &&
|
||||
(event->type == InputTypeShort)) {
|
||||
// Exit if Ended
|
||||
view_attack->callback(FuzzerCustomEventViewAttackBack, view_attack->context);
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
with_view_model(
|
||||
view_attack->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{
|
||||
if(model->attack_state == FuzzerAttackStateIdle) {
|
||||
if(!model->td_emt_cursor) {
|
||||
// TimeDelay ++
|
||||
if(event->type == InputTypeShort) {
|
||||
if(model->time_delay < FUZZ_TIME_DELAY_MAX) {
|
||||
model->time_delay++;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
model->time_delay += 10;
|
||||
if(model->time_delay > FUZZ_TIME_DELAY_MAX) {
|
||||
model->time_delay = FUZZ_TIME_DELAY_MAX;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// EmuTime ++
|
||||
if(event->type == InputTypeShort) {
|
||||
if(model->emu_time < FUZZ_TIME_DELAY_MAX) {
|
||||
model->emu_time++;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
model->emu_time += 10;
|
||||
if(model->emu_time > FUZZ_TIME_DELAY_MAX) {
|
||||
model->emu_time = FUZZ_TIME_DELAY_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Nothing
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(
|
||||
(event->key == InputKeyUp || event->key == InputKeyDown) &&
|
||||
event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
view_attack->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ model->td_emt_cursor = !model->td_emt_cursor; },
|
||||
true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_enter(void* context) {
|
||||
furi_assert(context);
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_exit(void* context) {
|
||||
furi_assert(context);
|
||||
FuzzerViewAttack* view_attack = context;
|
||||
with_view_model(
|
||||
view_attack->view, FuzzerViewAttackModel * model, { model->td_emt_cursor = false; }, true);
|
||||
}
|
||||
|
||||
FuzzerViewAttack* fuzzer_view_attack_alloc() {
|
||||
if(fuzzer_proto_get_max_data_size() > UID_MAX_DISPLAYED_LEN) {
|
||||
furi_crash("Maximum of displayed bytes exceeded");
|
||||
}
|
||||
|
||||
FuzzerViewAttack* view_attack = malloc(sizeof(FuzzerViewAttack));
|
||||
|
||||
// View allocation and configuration
|
||||
view_attack->view = view_alloc();
|
||||
view_allocate_model(view_attack->view, ViewModelTypeLocking, sizeof(FuzzerViewAttackModel));
|
||||
view_set_context(view_attack->view, view_attack);
|
||||
view_set_draw_callback(view_attack->view, (ViewDrawCallback)fuzzer_view_attack_draw);
|
||||
view_set_input_callback(view_attack->view, fuzzer_view_attack_input);
|
||||
view_set_enter_callback(view_attack->view, fuzzer_view_attack_enter);
|
||||
view_set_exit_callback(view_attack->view, fuzzer_view_attack_exit);
|
||||
|
||||
with_view_model(
|
||||
view_attack->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{
|
||||
model->time_delay = fuzzer_proto_get_def_idle_time();
|
||||
model->time_delay_min = 0; // model->time_delay;
|
||||
|
||||
model->emu_time = fuzzer_proto_get_def_emu_time();
|
||||
|
||||
model->emu_time_min = 2; // model->emu_time;
|
||||
|
||||
model->uid_str = furi_string_alloc_set_str("Not_set");
|
||||
// malloc(ATTACK_SCENE_MAX_UID_LENGTH + 1);
|
||||
model->attack_state = FuzzerAttackStateOff;
|
||||
model->td_emt_cursor = false;
|
||||
|
||||
// strcpy(model->uid_str, "Not_set");
|
||||
model->attack_name = "Not_set";
|
||||
model->protocol_name = "Not_set";
|
||||
},
|
||||
true);
|
||||
return view_attack;
|
||||
}
|
||||
|
||||
void fuzzer_view_attack_free(FuzzerViewAttack* view_attack) {
|
||||
furi_assert(view_attack);
|
||||
|
||||
with_view_model(
|
||||
view_attack->view,
|
||||
FuzzerViewAttackModel * model,
|
||||
{ furi_string_free(model->uid_str); },
|
||||
true);
|
||||
view_free(view_attack->view);
|
||||
free(view_attack);
|
||||
}
|
||||
|
||||
View* fuzzer_view_attack_get_view(FuzzerViewAttack* view_attack) {
|
||||
furi_assert(view_attack);
|
||||
return view_attack->view;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_view_attack_get_time_delay(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
uint8_t time_delay;
|
||||
|
||||
with_view_model(
|
||||
view->view, FuzzerViewAttackModel * model, { time_delay = model->time_delay; }, false);
|
||||
|
||||
return time_delay;
|
||||
}
|
||||
|
||||
uint8_t fuzzer_view_attack_get_emu_time(FuzzerViewAttack* view) {
|
||||
furi_assert(view);
|
||||
uint8_t emu_time;
|
||||
|
||||
with_view_model(
|
||||
view->view, FuzzerViewAttackModel * model, { emu_time = model->emu_time; }, false);
|
||||
|
||||
return emu_time;
|
||||
}
|
||||
42
applications/external/multi_fuzzer/views/attack.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
#include "../helpers/fuzzer_types.h"
|
||||
|
||||
#include "../lib/worker/protocol.h"
|
||||
|
||||
typedef struct FuzzerViewAttack FuzzerViewAttack;
|
||||
|
||||
typedef void (*FuzzerViewAttackCallback)(FuzzerCustomEvent event, void* context);
|
||||
|
||||
void fuzzer_view_attack_set_callback(
|
||||
FuzzerViewAttack* view_attack,
|
||||
FuzzerViewAttackCallback callback,
|
||||
void* context);
|
||||
|
||||
FuzzerViewAttack* fuzzer_view_attack_alloc();
|
||||
|
||||
void fuzzer_view_attack_free(FuzzerViewAttack* view_attack);
|
||||
|
||||
View* fuzzer_view_attack_get_view(FuzzerViewAttack* view_attack);
|
||||
|
||||
void fuzzer_view_attack_reset_data(
|
||||
FuzzerViewAttack* view,
|
||||
const char* attack_name,
|
||||
const char* protocol_name);
|
||||
|
||||
void fuzzer_view_attack_set_uid(FuzzerViewAttack* view, const FuzzerPayload* uid);
|
||||
|
||||
void fuzzer_view_attack_start(FuzzerViewAttack* view);
|
||||
|
||||
void fuzzer_view_attack_stop(FuzzerViewAttack* view);
|
||||
|
||||
void fuzzer_view_attack_pause(FuzzerViewAttack* view);
|
||||
|
||||
void fuzzer_view_attack_end(FuzzerViewAttack* view);
|
||||
|
||||
uint8_t fuzzer_view_attack_get_time_delay(FuzzerViewAttack* view);
|
||||
|
||||
uint8_t fuzzer_view_attack_get_emu_time(FuzzerViewAttack* view);
|
||||
358
applications/external/multi_fuzzer/views/field_editor.c
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
#include "field_editor.h"
|
||||
#include "../fuzzer_i.h"
|
||||
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <toolbox/hex.h>
|
||||
|
||||
#define FIELD_EDITOR_V2
|
||||
|
||||
#define GUI_DISPLAY_WIDTH 128
|
||||
#define GUI_DISPLAY_HEIGHT 64
|
||||
|
||||
#define GUI_DISPLAY_HORIZONTAL_CENTER 64
|
||||
#define GUI_DISPLAY_VERTICAL_CENTER 32
|
||||
|
||||
#define UID_STR_LENGTH 25
|
||||
|
||||
#ifdef FIELD_EDITOR_V2
|
||||
#define EDITOR_STRING_Y 38
|
||||
#else
|
||||
#define EDITOR_STRING_Y 50
|
||||
#endif
|
||||
|
||||
struct FuzzerViewFieldEditor {
|
||||
View* view;
|
||||
FuzzerViewFieldEditorCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t* uid;
|
||||
uint8_t uid_size;
|
||||
|
||||
FuriString* uid_str;
|
||||
|
||||
uint8_t index;
|
||||
bool lo;
|
||||
bool allow_edit;
|
||||
} FuzzerViewFieldEditorModel;
|
||||
|
||||
void fuzzer_view_field_editor_set_callback(
|
||||
FuzzerViewFieldEditor* view_edit,
|
||||
FuzzerViewFieldEditorCallback callback,
|
||||
void* context) {
|
||||
furi_assert(view_edit);
|
||||
|
||||
view_edit->callback = callback;
|
||||
view_edit->context = context;
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_reset_data(
|
||||
FuzzerViewFieldEditor* view_edit,
|
||||
const FuzzerPayload* new_uid,
|
||||
bool allow_edit) {
|
||||
furi_assert(view_edit);
|
||||
furi_assert(new_uid->data);
|
||||
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
memcpy(model->uid, new_uid->data, new_uid->data_size);
|
||||
model->index = 0;
|
||||
model->lo = false;
|
||||
model->uid_size = new_uid->data_size;
|
||||
model->allow_edit = allow_edit;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_get_uid(FuzzerViewFieldEditor* view_edit, FuzzerPayload* output_uid) {
|
||||
furi_assert(view_edit);
|
||||
furi_assert(output_uid);
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
output_uid->data_size = model->uid_size;
|
||||
memcpy(output_uid->data, model->uid, model->uid_size);
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
uint8_t fuzzer_view_field_editor_get_index(FuzzerViewFieldEditor* view_edit) {
|
||||
furi_assert(view_edit);
|
||||
uint8_t index;
|
||||
with_view_model(
|
||||
view_edit->view, FuzzerViewFieldEditorModel * model, { index = model->index; }, true);
|
||||
return index;
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_draw(Canvas* canvas, FuzzerViewFieldEditorModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
#ifdef FIELD_EDITOR_V2
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->allow_edit) {
|
||||
canvas_draw_icon(canvas, 2, 4, &I_ButtonLeft_4x7);
|
||||
canvas_draw_icon(canvas, 8, 4, &I_ButtonRight_4x7);
|
||||
|
||||
canvas_draw_icon_ex(canvas, 62, 3, &I_Pin_arrow_up_7x9, IconRotation180);
|
||||
canvas_draw_icon(canvas, 69, 3, &I_Pin_arrow_up_7x9);
|
||||
|
||||
canvas_draw_str(canvas, 14, 10, "select byte");
|
||||
canvas_draw_str(canvas, 79, 10, "adjust byte");
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 35, 4, &I_ButtonLeft_4x7);
|
||||
canvas_draw_icon(canvas, 41, 4, &I_ButtonRight_4x7);
|
||||
canvas_draw_str(canvas, 49, 10, "select byte");
|
||||
}
|
||||
|
||||
char msg_index[18];
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", model->index);
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas, GUI_DISPLAY_HORIZONTAL_CENTER, 24, AlignCenter, AlignBottom, msg_index);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_icon(canvas, 4, 52, &I_Pin_back_arrow_10x8);
|
||||
canvas_draw_icon(canvas, 85, 52, &I_Ok_btn_9x9);
|
||||
|
||||
canvas_draw_str(canvas, 16, 60, "Back");
|
||||
canvas_draw_str(canvas, 96, 60, "Attack");
|
||||
#else
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER,
|
||||
5,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
"Left and right: select byte");
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER,
|
||||
15,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
"Up and down: adjust byte");
|
||||
|
||||
char msg_index[18];
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(msg_index, sizeof(msg_index), "Field index : %d", model->index);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, GUI_DISPLAY_HORIZONTAL_CENTER, 28, AlignCenter, AlignTop, msg_index);
|
||||
#endif
|
||||
// ####### Editor #######
|
||||
FuriString* temp_s = model->uid_str;
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
furi_string_reset(temp_s);
|
||||
for(int i = -3; i != 0; i++) {
|
||||
if(0 <= (model->index + i)) {
|
||||
furi_string_cat_printf(temp_s, "%02X ", model->uid[model->index + i]);
|
||||
}
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 52, EDITOR_STRING_Y, AlignRight, AlignBottom, furi_string_get_cstr(temp_s));
|
||||
|
||||
furi_string_reset(temp_s);
|
||||
for(int i = 1; i != 4; i++) {
|
||||
if((model->index + i) < model->uid_size) {
|
||||
furi_string_cat_printf(temp_s, " %02X", model->uid[model->index + i]);
|
||||
}
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 77, EDITOR_STRING_Y, AlignLeft, AlignBottom, furi_string_get_cstr(temp_s));
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
furi_string_reset(temp_s);
|
||||
furi_string_cat_printf(temp_s, "<%02X>", model->uid[model->index]);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER,
|
||||
EDITOR_STRING_Y,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
furi_string_get_cstr(temp_s));
|
||||
|
||||
uint16_t w = canvas_string_width(canvas, furi_string_get_cstr(temp_s));
|
||||
w -= 11; // '<' & '>'
|
||||
w /= 2;
|
||||
|
||||
if(model->allow_edit) {
|
||||
if(model->lo) {
|
||||
canvas_draw_line(
|
||||
canvas,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER + 1,
|
||||
EDITOR_STRING_Y + 2,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER + w,
|
||||
EDITOR_STRING_Y + 2);
|
||||
} else {
|
||||
canvas_draw_line(
|
||||
canvas,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER - w,
|
||||
EDITOR_STRING_Y + 2,
|
||||
GUI_DISPLAY_HORIZONTAL_CENTER - 1,
|
||||
EDITOR_STRING_Y + 2);
|
||||
}
|
||||
} else {
|
||||
// canvas_draw_line(
|
||||
// canvas,
|
||||
// GUI_DISPLAY_HORIZONTAL_CENTER - w,
|
||||
// EDITOR_STRING_Y + 2,
|
||||
// GUI_DISPLAY_HORIZONTAL_CENTER + w,
|
||||
// EDITOR_STRING_Y + 2);
|
||||
}
|
||||
// ####### Editor #######
|
||||
}
|
||||
|
||||
bool fuzzer_view_field_editor_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
FuzzerViewFieldEditor* view_edit = context;
|
||||
|
||||
if(event->key == InputKeyBack && event->type == InputTypeShort) {
|
||||
view_edit->callback(FuzzerCustomEventViewFieldEditorBack, view_edit->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
view_edit->callback(FuzzerCustomEventViewFieldEditorOk, view_edit->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
if(event->type == InputTypeShort) {
|
||||
if(!model->allow_edit) {
|
||||
model->lo = false;
|
||||
}
|
||||
if(model->index > 0 || model->lo) {
|
||||
if(!model->lo) {
|
||||
model->index--;
|
||||
}
|
||||
model->lo = !model->lo;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
model->index = 0;
|
||||
model->lo = false;
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
if(event->type == InputTypeShort) {
|
||||
if(!model->allow_edit) {
|
||||
model->lo = true;
|
||||
}
|
||||
if(model->index < (model->uid_size - 1) || !model->lo) {
|
||||
if(model->lo) {
|
||||
model->index++;
|
||||
}
|
||||
model->lo = !model->lo;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
model->index = model->uid_size - 1;
|
||||
model->lo = true;
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
if(event->type == InputTypeShort && model->allow_edit) {
|
||||
if(model->lo) {
|
||||
model->uid[model->index] = (model->uid[model->index] & 0xF0) |
|
||||
((model->uid[model->index] + 1) & 0x0F);
|
||||
} else {
|
||||
model->uid[model->index] = ((model->uid[model->index] + 0x10) & 0xF0) |
|
||||
(model->uid[model->index] & 0x0F);
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
if(event->type == InputTypeShort && model->allow_edit) {
|
||||
if(model->lo) {
|
||||
model->uid[model->index] = (model->uid[model->index] & 0xF0) |
|
||||
((model->uid[model->index] - 1) & 0x0F);
|
||||
} else {
|
||||
model->uid[model->index] = ((model->uid[model->index] - 0x10) & 0xF0) |
|
||||
(model->uid[model->index] & 0x0F);
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_enter(void* context) {
|
||||
furi_assert(context);
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_exit(void* context) {
|
||||
furi_assert(context);
|
||||
}
|
||||
|
||||
FuzzerViewFieldEditor* fuzzer_view_field_editor_alloc() {
|
||||
FuzzerViewFieldEditor* view_edit = malloc(sizeof(FuzzerViewFieldEditor));
|
||||
|
||||
// View allocation and configuration
|
||||
view_edit->view = view_alloc();
|
||||
view_allocate_model(view_edit->view, ViewModelTypeLocking, sizeof(FuzzerViewFieldEditorModel));
|
||||
view_set_context(view_edit->view, view_edit);
|
||||
view_set_draw_callback(view_edit->view, (ViewDrawCallback)fuzzer_view_field_editor_draw);
|
||||
view_set_input_callback(view_edit->view, fuzzer_view_field_editor_input);
|
||||
view_set_enter_callback(view_edit->view, fuzzer_view_field_editor_enter);
|
||||
view_set_exit_callback(view_edit->view, fuzzer_view_field_editor_exit);
|
||||
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
model->uid_str = furi_string_alloc();
|
||||
model->uid = malloc(fuzzer_proto_get_max_data_size());
|
||||
},
|
||||
true);
|
||||
|
||||
return view_edit;
|
||||
}
|
||||
|
||||
void fuzzer_view_field_editor_free(FuzzerViewFieldEditor* view_edit) {
|
||||
furi_assert(view_edit);
|
||||
|
||||
with_view_model(
|
||||
view_edit->view,
|
||||
FuzzerViewFieldEditorModel * model,
|
||||
{
|
||||
furi_string_free(model->uid_str);
|
||||
free(model->uid);
|
||||
},
|
||||
true);
|
||||
view_free(view_edit->view);
|
||||
free(view_edit);
|
||||
}
|
||||
|
||||
View* fuzzer_view_field_editor_get_view(FuzzerViewFieldEditor* view_edit) {
|
||||
furi_assert(view_edit);
|
||||
return view_edit->view;
|
||||
}
|
||||
29
applications/external/multi_fuzzer/views/field_editor.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
#include "../lib/worker/protocol.h"
|
||||
|
||||
typedef struct FuzzerViewFieldEditor FuzzerViewFieldEditor;
|
||||
|
||||
typedef void (*FuzzerViewFieldEditorCallback)(FuzzerCustomEvent event, void* context);
|
||||
|
||||
void fuzzer_view_field_editor_set_callback(
|
||||
FuzzerViewFieldEditor* view_attack,
|
||||
FuzzerViewFieldEditorCallback callback,
|
||||
void* context);
|
||||
|
||||
FuzzerViewFieldEditor* fuzzer_view_field_editor_alloc();
|
||||
|
||||
void fuzzer_view_field_editor_free(FuzzerViewFieldEditor* view_attack);
|
||||
|
||||
View* fuzzer_view_field_editor_get_view(FuzzerViewFieldEditor* view_attack);
|
||||
|
||||
void fuzzer_view_field_editor_reset_data(
|
||||
FuzzerViewFieldEditor* view_edit,
|
||||
const FuzzerPayload* new_uid,
|
||||
bool allow_edit);
|
||||
|
||||
void fuzzer_view_field_editor_get_uid(FuzzerViewFieldEditor* view_edit, FuzzerPayload* output_uid);
|
||||
|
||||
uint8_t fuzzer_view_field_editor_get_index(FuzzerViewFieldEditor* view_edit);
|
||||
235
applications/external/multi_fuzzer/views/main_menu.c
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
#include "main_menu.h"
|
||||
#include "../fuzzer_i.h"
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#include "../lib/worker/protocol.h"
|
||||
|
||||
#define PROTOCOL_NAME_Y 12
|
||||
// #define PROTOCOL_CAROUSEL
|
||||
|
||||
struct FuzzerViewMain {
|
||||
View* view;
|
||||
FuzzerViewMainCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t proto_index;
|
||||
uint8_t menu_index;
|
||||
uint8_t proto_max;
|
||||
uint8_t menu_max;
|
||||
} FuzzerViewMainModel;
|
||||
|
||||
void fuzzer_view_main_update_data(FuzzerViewMain* view, FuzzerState state) {
|
||||
furi_assert(view);
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
model->proto_index = state.proto_index;
|
||||
model->menu_index = state.menu_index;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_main_get_state(FuzzerViewMain* view, FuzzerState* state) {
|
||||
furi_assert(view);
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
state->proto_index = model->proto_index;
|
||||
state->menu_index = model->menu_index;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void fuzzer_view_main_set_callback(
|
||||
FuzzerViewMain* view,
|
||||
FuzzerViewMainCallback callback,
|
||||
void* context) {
|
||||
furi_assert(view);
|
||||
|
||||
view->callback = callback;
|
||||
view->context = context;
|
||||
}
|
||||
|
||||
void fuzzer_view_main_draw(Canvas* canvas, FuzzerViewMainModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
if(model->menu_index > 0) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
24,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
fuzzer_proto_get_menu_label(model->menu_index - 1));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 64, 36, AlignCenter, AlignTop, fuzzer_proto_get_menu_label(model->menu_index));
|
||||
|
||||
if(model->menu_index < (model->menu_max - 1)) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
48,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
fuzzer_proto_get_menu_label(model->menu_index + 1));
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 27, PROTOCOL_NAME_Y, AlignCenter, AlignBottom, "<");
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
64,
|
||||
PROTOCOL_NAME_Y,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
fuzzer_proto_get_name(model->proto_index));
|
||||
canvas_draw_str_aligned(canvas, 101, PROTOCOL_NAME_Y, AlignCenter, AlignBottom, ">");
|
||||
|
||||
#ifdef PROTOCOL_CAROUSEL
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
20,
|
||||
PROTOCOL_NAME_Y,
|
||||
AlignRight,
|
||||
AlignBottom,
|
||||
(model->proto_index > 0) ? fuzzer_proto_get_name(model->proto_index - 1) :
|
||||
fuzzer_proto_get_name((model->proto_max - 1)));
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
108,
|
||||
PROTOCOL_NAME_Y,
|
||||
AlignLeft,
|
||||
AlignBottom,
|
||||
(model->proto_index < (model->proto_max - 1)) ?
|
||||
fuzzer_proto_get_name(model->proto_index + 1) :
|
||||
fuzzer_proto_get_name(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fuzzer_view_main_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
FuzzerViewMain* view = context;
|
||||
|
||||
if(event->key == InputKeyBack &&
|
||||
(event->type == InputTypeLong || event->type == InputTypeShort)) {
|
||||
view->callback(FuzzerCustomEventViewMainBack, view->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyOk && event->type == InputTypeShort) {
|
||||
view->callback(FuzzerCustomEventViewMainOk, view->context);
|
||||
return true;
|
||||
} else if(event->key == InputKeyDown && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
if(model->menu_index < (model->menu_max - 1)) {
|
||||
model->menu_index++;
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyUp && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
if(model->menu_index != 0) {
|
||||
model->menu_index--;
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
if(model->proto_index != 0) {
|
||||
model->proto_index--;
|
||||
} else {
|
||||
model->proto_index = (model->proto_max - 1);
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
} else if(event->key == InputKeyRight && event->type == InputTypeShort) {
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
if(model->proto_index == (model->proto_max - 1)) {
|
||||
model->proto_index = 0;
|
||||
} else {
|
||||
model->proto_index++;
|
||||
}
|
||||
},
|
||||
true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void fuzzer_view_main_enter(void* context) {
|
||||
furi_assert(context);
|
||||
}
|
||||
|
||||
void fuzzer_view_main_exit(void* context) {
|
||||
furi_assert(context);
|
||||
}
|
||||
|
||||
FuzzerViewMain* fuzzer_view_main_alloc() {
|
||||
FuzzerViewMain* view = malloc(sizeof(FuzzerViewMain));
|
||||
|
||||
// View allocation and configuration
|
||||
view->view = view_alloc();
|
||||
view_allocate_model(view->view, ViewModelTypeLocking, sizeof(FuzzerViewMainModel));
|
||||
view_set_context(view->view, view);
|
||||
view_set_draw_callback(view->view, (ViewDrawCallback)fuzzer_view_main_draw);
|
||||
view_set_input_callback(view->view, fuzzer_view_main_input);
|
||||
view_set_enter_callback(view->view, fuzzer_view_main_enter);
|
||||
view_set_exit_callback(view->view, fuzzer_view_main_exit);
|
||||
|
||||
with_view_model(
|
||||
view->view,
|
||||
FuzzerViewMainModel * model,
|
||||
{
|
||||
model->proto_index = 0;
|
||||
model->proto_max = fuzzer_proto_get_count_of_protocols();
|
||||
model->menu_index = 0;
|
||||
model->menu_max = fuzzer_proto_get_count_of_menu_items();
|
||||
},
|
||||
true);
|
||||
return view;
|
||||
}
|
||||
|
||||
void fuzzer_view_main_free(FuzzerViewMain* view) {
|
||||
furi_assert(view);
|
||||
|
||||
// with_view_model(
|
||||
// view->view,
|
||||
// FuzzerViewMainModel * model,
|
||||
// {
|
||||
|
||||
// },
|
||||
// true);
|
||||
view_free(view->view);
|
||||
free(view);
|
||||
}
|
||||
|
||||
View* fuzzer_view_main_get_view(FuzzerViewMain* view) {
|
||||
furi_assert(view);
|
||||
return view->view;
|
||||
}
|
||||
23
applications/external/multi_fuzzer/views/main_menu.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../helpers/fuzzer_custom_event.h"
|
||||
#include "../helpers/fuzzer_types.h"
|
||||
|
||||
typedef struct FuzzerViewMain FuzzerViewMain;
|
||||
|
||||
typedef void (*FuzzerViewMainCallback)(FuzzerCustomEvent event, void* context);
|
||||
|
||||
void fuzzer_view_main_set_callback(
|
||||
FuzzerViewMain* fuzzer_view_main,
|
||||
FuzzerViewMainCallback callback,
|
||||
void* context);
|
||||
|
||||
FuzzerViewMain* fuzzer_view_main_alloc();
|
||||
|
||||
void fuzzer_view_main_free(FuzzerViewMain* view);
|
||||
|
||||
View* fuzzer_view_main_get_view(FuzzerViewMain* view);
|
||||
|
||||
void fuzzer_view_main_update_data(FuzzerViewMain* view, FuzzerState state);
|
||||
void fuzzer_view_main_get_state(FuzzerViewMain* view, FuzzerState* state);
|
||||