1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 20:49:49 +04:00

Merge pull request #507 from gid9798/Fuzzer

New RFID(125) and iButton Fuzzers
This commit is contained in:
MX
2023-06-08 02:13:35 +03:00
committed by GitHub
62 changed files with 2953 additions and 3454 deletions

View File

@@ -134,7 +134,8 @@ You can support us by using links or addresses below:
### Community apps included: ### 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 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) - **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) - 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) - 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) - **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) - 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) - HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer)
- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager) - 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) - Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)

View File

@@ -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.
* ----------------------------------------------------------------------------
*/

View File

@@ -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`

View File

@@ -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",
)

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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]));
}
}
}
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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.
* ----------------------------------------------------------------------------
*/

View File

@@ -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",
)

View File

@@ -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;
}

View File

@@ -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;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

View File

@@ -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]));
}
}
}
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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);

View 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",
)

View 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;
}

View 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;

View File

@@ -0,0 +1,17 @@
#pragma once
typedef enum {
// FuzzerCustomEvent
FuzzerCustomEventViewMainBack = 100,
FuzzerCustomEventViewMainOk,
FuzzerCustomEventViewMainPopupErr,
FuzzerCustomEventViewAttackBack,
FuzzerCustomEventViewAttackOk,
// FuzzerCustomEventViewAttackTick, // now not use
FuzzerCustomEventViewAttackEnd,
FuzzerCustomEventViewFieldEditorBack,
FuzzerCustomEventViewFieldEditorOk,
} FuzzerCustomEvent;

View 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;

View File

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View 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;
}

View 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);

View 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);
}

View 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();

View 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[];

View 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,
};

View 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

View 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);
}

View File

@@ -0,0 +1,3 @@
ADD_SCENE(fuzzer, main, Main)
ADD_SCENE(fuzzer, attack, Attack)
ADD_SCENE(fuzzer, field_editor, FieldEditor)

View 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);
}

View 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);
}

View 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`

View 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;
}

View 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);

View 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;
}

View 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);

View 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;
}

View 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);