Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Spoofing a Character Device

In this guide, we will virtually spoof a radar sensor for a drone application. The software expects a device at /dev/radar, but we will provide it entirely through software.

The Target Application

Our C application attempts to open the radar and read its configuration.

certo_symbol_import_demo.h

struct RadarConfig {
    int range;
    int sweep_speed;
    char status[16];
};

main.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "certo_symbol_import_demo.h"

int main() {
    // 1. Attempt to connect to the physical hardware
    int fd = open("/dev/radar", O_RDONLY);
    if (fd < 0) {
        printf("CRITICAL ERROR: Radar hardware not found!\n");
        return -1;
    }

    // 2. Read the hardware's internal configuration
    struct RadarConfig my_radar;
    read(fd, &my_radar, sizeof(my_radar));

    printf("Radar Online! Range: %d, Status: %s\n", my_radar.range, my_radar.status);

    // 3. Teardown
    close(fd);
    return 0;
}

Step 1: Target and Schema

  1. Create a new Hardware Spec in Certo.
  2. Set the intercept target path to /dev/radar.
  3. Import certo_symbol_import_demo.h to map the RadarConfig struct.

Step 2: The open Hook

Intercept the initialization to tell the app the hardware is connected.

certo::logger "Intercepted attempt to open /dev/radar!"

# Initialize our virtual hardware state
set ::radar_is_healthy 1

# Bypass real OS and return a fake File Descriptor (e.g., 99)
certo_set_return_value 99

Step 3: The read Hook

Generate the structured data and write it to the app's memory.

::certo::logger info "Application requested Radar data."

# 1. Create a zeroed-out dictionary based on our C-Schema
set my_radar [::certo::create_struct "RadarConfig"]

# 2. Populate the dict based on virtual state
if {$::radar_is_healthy == 1} {
    dict set my_radar range 10000
    dict set my_radar sweep_speed 5
    dict set my_radar status "ACTIVE"
} else {
    dict set my_radar status "OFFLINE"
}

# 3. Convert to raw bytes and write to the app's pointer
set raw_bytes [::certo::dict_to_bytes "RadarConfig" $my_radar]
set buf_addr [lindex $certo::arguments 1]
::certo::write_memory $buf_addr $raw_bytes

# 4. Return the requested size to indicate success
set requested_size [lindex $certo::arguments 2]
certo_set_return_value $requested_size