This guide covers Flipper Zero firmware development for legitimate security research, penetration testing with authorization, and educational purposes only. Unauthorized access to systems, devices, or networks is illegal.

Authorized Use Cases:

  • ✅ Testing your own devices
  • ✅ Authorized penetration testing
  • ✅ Educational research and learning
  • ✅ IoT device security auditing (with permission)

Never:

  • ❌ Access systems without explicit authorization
  • ❌ Interfere with critical infrastructure
  • ❌ Jam emergency communications
  • ❌ Clone access badges/cards you don’t own

Research Disclaimer

This tutorial is based on:

  • Flipper Zero Firmware (ufbt-based development, 2024-2025)
  • Flipper Application Framework (FAP) for custom apps
  • Official Flipper Zero Documentation (https://docs.flipper.net/)
  • C programming for STM32WB55 microcontroller
  • FreeRTOS and Flipper API v1.x

All code examples follow documented Flipper Zero SDK patterns. This guide focuses on defensive security research and understanding IoT security concepts.

Introduction

The Flipper Zero is a portable multi-tool for pentesters and hardware hackers, supporting RFID, NFC, Sub-GHz, infrared, BadUSB, and GPIO. This guide demonstrates firmware development using the official Flipper Application Framework.

Key Topics:

  • Custom application development with Flipper SDK
  • GUI development with Canvas and ViewPort
  • Event handling and input processing
  • GPIO and LED control
  • Application lifecycle management
  • Memory management and resource cleanup

Flipper Zero Capabilities

Feature Use Case Security Research Application
125kHz RFID Read EM4100, HID Prox Test physical access control systems
13.56MHz NFC Read/emulate MIF are, NTAG Audit NFC-based authentication
Sub-GHz 300-928 MHz signals Analyze garage doors, wireless sensors
Infrared TV/AC remotes Study IR communication protocols
BadUSB USB HID keyboard Test endpoint security controls
iButton Dallas 1-Wire Audit legacy access systems
GPIO External hardware Interface with custom circuits

Prerequisites

Required Knowledge:

  • C programming basics
  • Understanding of embedded systems
  • Familiarity with Git and command line
  • Basic electronics (optional but helpful)

Required Tools:

# Install Flipper Build Tool (ufbt)
pip3 install ufbt

# Update ufbt SDK
ufbt update

# Clone Flipper Zero firmware (for reference)
git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git

Hardware:

  • Flipper Zero device
  • USB-C cable
  • (Optional) Logic analyzer for debugging
  • (Optional) External sensors/modules for GPIO

Flipper Zero Architecture

┌─────────────────────────────────────────────┐
│  Flipper Zero (STM32WB55)                   │
│  ┌───────────────────────────────────────┐  │
│  │  Applications Layer                   │  │
│  │  - Built-in apps (RFID, NFC, etc.)    │  │
│  │  - Custom FAPs (Flipper Apps)         │  │
│  └───────────────────────────────────────┘  │
│  ┌───────────────────────────────────────┐  │
│  │  Flipper API (furi, gui, storage...)  │  │
│  └───────────────────────────────────────┘  │
│  ┌───────────────────────────────────────┐  │
│  │  FreeRTOS                              │  │
│  └───────────────────────────────────────┘  │
│  ┌───────────────────────────────────────┐  │
│  │  Hardware (RF, NFC, GPIO, Display)    │  │
│  └───────────────────────────────────────┘  │
└─────────────────────────────────────────────┘

Example 1: Hello World Application

Create Basic App Structure

File: hello_world/application.fam - App metadata

App(
    appid="hello_world",
    name="Hello World",
    apptype=FlipperAppType.EXTERNAL,
    entry_point="hello_world_app",
    requires=[
        "gui",
    ],
    stack_size=2 * 1024,
    fap_icon="icon.png",
    fap_category="Misc",
)

File: hello_world/hello_world.c - Main application

/**
 * Hello World app for Flipper Zero
 * Demonstrates basic GUI and input handling
 */

#include <furi.h>
#include <gui/gui.h>
#include <input/input.h>

typedef struct {
    Gui* gui;
    ViewPort* view_port;
    FuriMessageQueue* event_queue;
    int counter;
} HelloWorldApp;

typedef enum {
    EventTypeInput,
} EventType;

typedef struct {
    EventType type;
    InputEvent input;
} AppEvent;

// Draw callback
static void hello_world_draw_callback(Canvas* canvas, void* ctx) {
    HelloWorldApp* app = ctx;

    canvas_clear(canvas);
    canvas_set_font(canvas, FontPrimary);
    canvas_draw_str(canvas, 10, 20, "Hello, Flipper!");

    canvas_set_font(canvas, FontSecondary);
    char counter_str[32];
    snprintf(counter_str, sizeof(counter_str), "Counter: %d", app->counter);
    canvas_draw_str(canvas, 10, 35, counter_str);

    canvas_draw_str(canvas, 10, 55, "Press OK to increment");
}

// Input callback
static void hello_world_input_callback(InputEvent* event, void* ctx) {
    HelloWorldApp* app = ctx;

    // Send event to queue
    AppEvent app_event = {.type = EventTypeInput, .input = *event};
    furi_message_queue_put(app->event_queue, &app_event, 0);
}

// App entry point
int32_t hello_world_app(void* p) {
    UNUSED(p);

    // Allocate app structure
    HelloWorldApp* app = malloc(sizeof(HelloWorldApp));
    app->counter = 0;

    // Create event queue
    app->event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));

    // Setup GUI
    app->gui = furi_record_open(RECORD_GUI);
    app->view_port = view_port_alloc();

    view_port_draw_callback_set(app->view_port, hello_world_draw_callback, app);
    view_port_input_callback_set(app->view_port, hello_world_input_callback, app);

    gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);

    // Event loop
    AppEvent event;
    bool running = true;

    while(running) {
        if(furi_message_queue_get(app->event_queue, &event, 100) == FuriStatusOk) {
            if(event.type == EventTypeInput) {
                if(event.input.key == InputKeyOk && event.input.type == InputTypeShort) {
                    // Increment counter on OK press
                    app->counter++;
                    view_port_update(app->view_port);
                } else if(event.input.key == InputKeyBack) {
                    // Exit on back button
                    running = false;
                }
            }
        }
    }

    // Cleanup
    gui_remove_view_port(app->gui, app->view_port);
    view_port_free(app->view_port);
    furi_record_close(RECORD_GUI);
    furi_message_queue_free(app->event_queue);
    free(app);

    return 0;
}

Build and run:

cd hello_world
ufbt
ufbt launch  # Flash and run on connected Flipper Zero

Example 2: GPIO LED Controller

Control external LED via GPIO pins.

File: gpio_led/gpio_led.c

/**
 * GPIO LED controller for Flipper Zero
 * Demonstrates GPIO pin control
 */

#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <input/input.h>

// GPIO pin definitions (Flipper Zero external GPIO)
#define LED_PIN &gpio_ext_pa7  // Pin 2 on ext connector

typedef struct {
    Gui* gui;
    ViewPort* view_port;
    FuriMessageQueue* event_queue;
    bool led_state;
} GpioLedApp;

typedef struct {
    InputEvent input;
} AppEvent;

static void gpio_led_draw(Canvas* canvas, void* ctx) {
    GpioLedApp* app = ctx;

    canvas_clear(canvas);
    canvas_set_font(canvas, FontPrimary);
    canvas_draw_str(canvas, 10, 20, "GPIO LED Control");

    canvas_set_font(canvas, FontSecondary);
    canvas_draw_str(canvas, 10, 35, app->led_state ? "LED: ON" : "LED: OFF");
    canvas_draw_str(canvas, 10, 50, "Press OK to toggle");
}

static void gpio_led_input(InputEvent* event, void* ctx) {
    GpioLedApp* app = ctx;
    AppEvent app_event = {.input = *event};
    furi_message_queue_put(app->event_queue, &app_event, 0);
}

int32_t gpio_led_app(void* p) {
    UNUSED(p);

    GpioLedApp* app = malloc(sizeof(GpioLedApp));
    app->led_state = false;
    app->event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));

    // Initialize GPIO
    furi_hal_gpio_init_simple(LED_PIN, GpioModeOutputPushPull);
    furi_hal_gpio_write(LED_PIN, false);

    // Setup GUI
    app->gui = furi_record_open(RECORD_GUI);
    app->view_port = view_port_alloc();
    view_port_draw_callback_set(app->view_port, gpio_led_draw, app);
    view_port_input_callback_set(app->view_port, gpio_led_input, app);
    gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);

    // Event loop
    AppEvent event;
    bool running = true;

    while(running) {
        if(furi_message_queue_get(app->event_queue, &event, 100) == FuriStatusOk) {
            if(event.input.key == InputKeyOk && event.input.type == InputTypeShort) {
                // Toggle LED
                app->led_state = !app->led_state;
                furi_hal_gpio_write(LED_PIN, app->led_state);
                view_port_update(app->view_port);
            } else if(event.input.key == InputKeyBack) {
                running = false;
            }
        }
    }

    // Cleanup
    furi_hal_gpio_write(LED_PIN, false);  // Turn off LED
    gui_remove_view_port(app->gui, app->view_port);
    view_port_free(app->view_port);
    furi_record_close(RECORD_GUI);
    furi_message_queue_free(app->event_queue);
    free(app);

    return 0;
}

Building Real-World Applications

The examples above provide the foundation for building more complex Flipper Zero applications. Key patterns to follow:

1. Proper Resource Management:

  • Always free allocated memory and resources
  • Close records when done (furi_record_close())
  • Clean up GPIO states on exit

2. Event-Driven Architecture:

  • Use message queues for inter-task communication
  • Implement proper event loops with timeouts
  • Handle all input types (short press, long press, release)

3. User Interface Best Practices:

  • Provide clear visual feedback
  • Handle all button inputs (including Back for exit)
  • Update display only when state changes

4. Hardware Interaction:

  • Initialize hardware before use
  • Check return values from HAL functions
  • Reset hardware to safe state on cleanup

Expanding to Advanced Features

Once comfortable with basic GUI and GPIO control, explore:

RFID/NFC Development:

  • Study official Flipper RFID app implementation
  • Use lib/lfrfid and lib/nfc libraries
  • Always test with devices you own

Sub-GHz Communication:

  • Reference official Sub-GHz app for proper API usage
  • Understand regional frequency restrictions
  • Obtain authorization before testing wireless systems

BadUSB (HID) Automation:

  • Use lib/badusb for USB HID emulation
  • Create scripts for authorized penetration testing
  • Test on isolated systems first

Security Testing Workflows

1. RFID Access Control Testing

Authorized testing workflow:

# RFID Security Audit Checklist

## Preparation
- [ ] Obtain written authorization from facility owner
- [ ] Document test scope and objectives
- [ ] Identify RFID system type (125kHz EM4100, HID Prox, etc.)

## Testing
- [ ] Read access card with Flipper Zero
- [ ] Document card UID and protocol
- [ ] Test for card cloning vulnerability
- [ ] Test for replay attack susceptibility
- [ ] Verify encryption (if applicable)

## Reporting
- [ ] Document findings
- [ ] Provide remediation recommendations
- [ ] Suggest migration to secure alternatives (NFC with encryption)

2. Wireless Sensor Audit

Authorized testing for IoT sensors:

# Capture Sub-GHz signals from authorized devices
# Example: Testing your own garage door opener

# 1. Set frequency (check device specs)
# 2. Capture signal
# 3. Analyze protocol
# 4. Test for replay attacks
# 5. Document vulnerabilities

Known Limitations

Limitation Impact Mitigation
Legal restrictions Illegal use of certain features Only use with authorization, check local laws
Encrypted systems Cannot clone modern secure cards Document as secure finding
Range limitations ~10cm for RFID, varies for Sub-GHz Use for close-range testing only
Battery life Limited runtime for continuous scanning Use external battery pack
Firmware updates API changes between versions Test with specific firmware version
Debug complexity Hard to debug embedded apps Use serial console, logic analyzer

Conclusion

Flipper Zero firmware development provides a powerful platform for building custom security research tools:

  • C-based development with modern Flipper SDK and ufbt toolchain
  • Event-driven architecture using FreeRTOS and Furi framework
  • GUI development with Canvas and ViewPort APIs
  • GPIO control for interfacing with external hardware
  • Foundation for building advanced RFID, NFC, and wireless applications

Key Takeaways:

  • Start with simple GUI and GPIO examples before advanced features
  • Follow proper resource management patterns (allocate → use → free)
  • Study official Flipper apps for reference implementations
  • Always obtain authorization before security testing
  • Test responsibly with devices you own

Next Steps:

  • Explore official Flipper firmware apps for advanced API usage
  • Reference flipperzero-firmware repository for RFID/NFC/Sub-GHz implementations
  • Join Flipper Zero community (Discord, forum) for support
  • Build custom tools for authorized security research
  • Contribute improvements back to the community

Further Resources: