Skip to content

Latest commit

 

History

History
364 lines (285 loc) · 20.9 KB

File metadata and controls

364 lines (285 loc) · 20.9 KB

IoT Firmware Emulation Decision Guide

Emulation is a way to answer a research question, not a success condition by itself. Use the smallest execution layer that can change your decision.

Source Basis

Claim area Source
QEMU user-mode runs foreign-architecture user programs on the host OS and translates syscalls QEMU user-mode documentation
QEMU system emulation models a machine with CPU, memory, and emulated devices for a guest OS QEMU system-emulation documentation
Single-service rehosting can avoid full-device fidelity for Linux firmware services Greenhouse, USENIX Security 2023
Large-scale full-system IoT rehosting depends on environment-recovery heuristics FirmAE repository, FirmAE publication record
Peripheral behavior can be modeled only as needed to reach a point of interest Jetset, USENIX Security 2021
Kernel-module questions may require userland plus kernel-level rehosting Pandawan repository
MCU firmware is blocked by peripheral and interrupt behavior, not just CPU ISA P2IM, USENIX Security 2020
EMBA L10/S115/S130 behavior in this repository EMBA source-code capability map
A focused web-service harness can be enough for exploit development when route, CGI, auth state, and process context are known Claroty Team82 Planet WGS-804HPT industrial switch research
A custom analysis OS can import vendor rootfs/firmware while exposing debug tools, NVRAM preload, NFS/shared files, and optional MTD flash ARMX Firmware Emulation Framework, local emulation folder
Raw NAND/UBI reconstruction is justified when persistent state is outside the rootfs Local Gemtek case: README, set-nandsim.sh
JFFS2/UBIFS reconstruction may depend on OOB/ECC, VID offset, bad-block reserve, and volume metadata Claroty Avaya IP phone, Unauthorized Access Connexoon, Youngrok nandsim and UBIFS partitioning
eMMC storage has different evidence semantics from raw NAND/MTD Youngrok eMMC raw access notes

The ordering and scoring guidance below is a synthesized heuristic derived from those sources and the local EMBA source code.

What Each Layer Proves

Layer What it can prove What it cannot prove Minimum evidence output
Static analysis Files, versions, routes, startup scripts, caller/sink relationships Runtime reachability, board state, exact service behavior Input-to-sink graph with file/function evidence
QEMU-user One ELF can execute far enough to expose version/help output, syscall/file dependencies, parser behavior, or a crash under host-kernel syscall translation Full device boot, real kernel behavior, real NVRAM/peripherals, network service defaults Command, stdout/stderr, exit status, QEMU_STRACE/strace, breakpoint/crash
Service harness/chroot A target service can start with selected libraries/config/env and receive requests Faithful init, board devices, flash layout, hardware-backed state Listener, request/response, missing-file/device/syscall list
Custom analysis OS / Buildroot guest Vendor binaries run inside a controlled guest with compatible libc/kernel choices, debug tools, imported rootfs, and optional flash/NVRAM data Original bootloader, board peripherals, exact init, production network exposure Guest kernel/config, imported paths, launch commands, debug logs, synthetic assumptions
Full-system QEMU/FirmAE/EMBA L10 Kernel/init/network/service hypotheses in a repaired generic machine Exact target SoC, boot ROM, fuses, proprietary peripherals, original launch conditions Serial log, process list, port scan, launch command, filesystem repairs
MTD/UBI simulation Kernel MTD semantics for a raw flash partition: eraseblocks, UBI attach, JFFS2/UBIFS mount behavior, and /dev/mtd* consumers Secret material that was not present in the raw dump; vendor flash-controller ECC behavior unless modeled /proc/mtd, ubiattach/mount output, partition geometry, files recovered from persistent storage
Hardware Peripheral, boot-chain, flash, radio, secure-element, timing, and board-state evidence Broad static coverage by itself Boot log, read-only flash, pin/state observation, debug trace

Escalation Algorithm

Write the unknown first:

Question:
Current evidence:
Two possible explanations:
Observation that would distinguish them:
Cheapest experiment:
Abandon condition:

Then choose:

file/version/route/sink question -> static
one binary/parser/version question -> QEMU-user
service startup/request question -> service harness
old libc/kernel/debug-tool compatibility question -> custom analysis OS
init/kernel/network/multiple-service question -> full-system emulation
peripheral/boot ROM/fuse/radio/flash-layout question -> hardware

Escalate only if the next layer can produce an observation that the previous layer cannot. If both hypotheses would look the same in QEMU-user, QEMU-user is not the next experiment.

Flash-Backed Persistence And MTD Simulation

Use nandsim, mtdram, ubiattach, JFFS2, or UBIFS tooling when the lead depends on kernel MTD semantics or a persistent partition outside the extracted rootfs. Do not use it merely because the device uses NAND.

The local Gemtek WVRTM-127ACN case shows the trigger pattern. The writeup records a 128 MB NAND dump, page and erase geometry (writesize=2048, oobsize=64, erasesize=131072), a partition table with Config, Env, Kernel, and Storage partitions, and boot evidence that mtd8 is attached as ubi8 and mounted as UBIFS at /mnt/jffs2. The project script then loads nandsim with matching partition sizes, erases /dev/mtd0 through /dev/mtd8, writes each partition image with nandwrite, and mounts /dev/ubi8_0 at /mnt/jffs2. README, set-nandsim.sh

That evidence changes the decision:

Observation Interpretation Cheapest next experiment Abandon condition
Secrets or accounts are absent from SquashFS but init links /etc into /mnt/jffs2 persistent UBIFS may be the real credential/config store reconstruct the UBI partition read-only and list mounted files raw dump lacks the relevant partition or mount geometry cannot be supported
Boot log shows UBI: attached mtd8 to ubi8 and UBIFS: mounted kernel MTD/UBI behavior is part of the runtime filesystem attach the matching MTD partition with the recorded VID/header offset attach succeeds but recovered files do not feed the lead
Binaries or scripts read /dev/mtd*, /proc/mtd, U-Boot env, factory, caldata, or storage partitions QEMU-user alone will miss the storage contract provide an MTD/UBI-backed harness only for that consumer the consumer only needs a constant value that static analysis already proves
Default password is generated by one helper from serial/MAC inputs NAND simulation may be unnecessary reverse or run the helper with vendor libraries and known inputs no flash-backed value is consumed by the algorithm
Secret is expected to be per-device but only a vendor update package is available simulation would create empty or generic state search the package for raw config/factory images first no raw partition image exists; hardware read is the next scoped question

What this proves:

the dumped partition can be interpreted with the chosen MTD/UBI parameters
files or values exist in that recovered persistent storage
a script/binary path can consume those files or values

What it does not prove:

secrets that were never present in the dump
bad-block, OOB, ECC, or vendor controller behavior unless captured or modeled
that a service is reachable on the original board
that generated first-boot state matches a clean device unless the boot path is reproduced

False-positive risks are high when page size, eraseblock size, OOB handling, bad-block policy, UBI VID/header offset, or partition boundaries are guessed. A failed mount with guessed geometry is not evidence that the device lacks the secret. A successful mount of a synthetic empty partition is also not evidence about a shipped device.

Use the practitioner examples to classify failures:

Failure or blocker Likely meaning Next action
JFFS2 mount works only after partition splitting filesystem nodes from different partitions were being mixed recover partition table before interpreting files
mount/write-back fails with ECC errors OOB/ECC layout is controller-specific preserve OOB evidence and avoid write-back claims until ECC is understood
UBI attach succeeds but available LEBs are unexpectedly low bad-block reserve or volume sizing changed capacity inspect ubinfo, ubiattach -b, VID offset, and ubinize parameters
extracted update has UBI volumes but no per-device data update package is not the same as a full flash dump downgrade secret claims or move to scoped hardware acquisition
target uses /dev/mmcblk* instead of /dev/mtd* eMMC/SD partition semantics, not NAND MTD semantics inspect GPT/MBR, boot partitions, read-only flags, and secure/RPMB-like areas
repeated test writes risk flash wear dynamic experiment may damage the target use removable-media pivot, overlay, emulator, or read-only proof first

QEMU-User Interpretation

QEMU user-mode is strong evidence for local userland behavior. It is weak evidence for device behavior.

Use it when:

  • a parser can be exercised by a file or packet-like buffer;
  • a CGI/helper binary needs vendor libraries;
  • version/help output is needed for SBOM/CVE triage;
  • missing files or syscalls will tell you which config gates a path;
  • a crash must be tied to controlled input before heavier work.

Record:

binary hash
architecture and endian
dynamic loader and library path
rootfs prefix
environment variables
arguments and input file
stdout/stderr/exit
strace/QEMU_STRACE findings

Do not claim network reachability, daemon default state, privilege context, or hardware behavior from QEMU-user alone. QEMU's own documentation describes user-mode as launching programs compiled for another CPU on the same OS, with syscall translation; that is not a virtual board.

Service Harness Interpretation

A service harness is the middle path between one binary and the whole device. It is justified when the claim depends on a listener, route, config file, environment variable, or adjacent helper process.

Good harness questions:

  • Does /cgi-bin/diag reach the handler named in the config?
  • Does the service parse this request before authentication?
  • Which missing NVRAM key decides whether the route is enabled?
  • Does the daemon run as root in the original startup script?

False-positive risks:

  • You supplied config that the device would not ship with.
  • You disabled authentication or feature gates accidentally.
  • You launched a helper outside the original working directory/user/env.
  • You satisfied /dev, /proc, /sys, or NVRAM with synthetic values.

Before using a harness result in a report, compare it against original startup files and record every synthetic file, argument, and environment variable.

The Claroty Planet WGS-804HPT case is the useful boundary: they extracted the firmware, selected the Boa web service because it was the network-facing management component, mapped dispatcher.cgi as a pre-auth CGI target, then used QEMU/chroot and QEMU GDB support to validate the vulnerable cookie path. The reusable rule is not "emulate the whole switch"; it is "emulate the component whose route, auth state, and sink already make it the highest-value candidate."

Custom Analysis OS / Buildroot Guest Interpretation

Use this pattern when a normal chroot is too thin, but faithful board emulation is not the research question. You build or reuse a Linux guest that is close enough for the target binaries, then import the vendor rootfs, firmware partitions, debug tools, and storage scripts.

Good triggers:

  • QEMU-user finds libc, loader, thread, crypto, or kernel-version mismatches that block the target binary;
  • the target needs old uClibc/glibc, libgcrypt, kernel headers, or GDB support that are easier to reproduce with Buildroot than on the host;
  • you need strace, ltrace, gdbserver, SSH, or file-transfer tools inside the guest while keeping the vendor rootfs mostly separate;
  • the lead depends on imported firmware files, update packages, NVRAM data, or MTD/UBI experiments, but not on exact board peripherals.

Local examples:

Example What it builds What it imports Decision lesson
emulation/myrootfs old ARM/XScale-style Linux rootfs and toolchains printer flash-root artifacts for selected binaries use an older build environment when modern libc/toolchains distort behavior
emulation/buildroot-armv7 ARMv7 vexpress-a9 Buildroot guest with Linux 3.4.11-rt19, uClibc, debug tools, MTD/UBI utilities Netgear DVA rootfs under /dva-root and firmware under /dva-firm build a compatible analysis OS, not a faithful router, when sig_verify and update-chain binaries are the target
emulation/hht MIPS Malta Buildroot guest for the Hardware Hacking Tutorial/Gemtek-style workflow router rootfs and set-nandsim.sh preserve old Buildroot/uClibc compatibility and flash tooling when the research needs it
NB6VAC emulation early MIPS/Buildroot 2015.02 environment with UBIFS/JFFS2 tooling NB6VAC artifacts and kernel/rootfs work treat partial emulation as a hardware/rootfs experiment, not a secure-boot conclusion
ARMX Docker-packaged ARM/QEMU framework with per-device config, NFS-shared /armx, NVRAM preload, optional flash memory, and helper commands rootfs archives, nvram.ini, optional flashmem, preload libraries formalize device onboarding with config, NVRAM, flash, port forwarding, and debug logs

Evidence to record:

why QEMU-user/chroot was insufficient
guest CPU/machine/kernel/libc/toolchain versions
vendor rootfs and firmware import paths
original startup evidence versus guest launch commands
debug tools added to the guest
NVRAM, flash, `/proc`, `/sys`, `/dev`, or preload assumptions
which observation promoted or rejected the lead

False-positive risks:

  • the guest kernel accepts behavior the original kernel would reject;
  • imported rootfs paths are convenient but not original mount points;
  • NVRAM or flash values are defaults, guesses, or copied from another device;
  • Docker bind mounts expose more host state than the experiment needs;
  • debug-friendly compiler flags, disabled stripping, or added libraries change timing, memory layout, or loader behavior.

Mount only the workspace needed to preserve paths. The local Buildroot examples often mount the user's whole home directory so old scripts can see sibling buildroot-*, firmware, and project directories at identical absolute paths. That is a convenience pattern, not an evidence requirement. Prefer mounting the smallest project parent that contains the Buildroot tree, emulation tree, and firmware inputs.

Abandon this branch when the setup becomes a toolchain archaeology project and the lead can be answered by static analysis, targeted QEMU-user, or a simpler service harness. Reopen it when a specific binary or update-chain question requires the old userspace/kernel/debug environment.

Full-System Emulation Interpretation

Use full-system emulation when init, kernel, networking, or multiple services are material to the claim. It is not a certificate of device fidelity.

FirmAE reports large improvements over Firmadyne by applying arbitration heuristics to boot, network, NVRAM, kernel, and filesystem issues. That is the important lesson: successful rehosting often requires environment repair.

For EMBA specifically, read emba-source-capability-map.md before interpreting L10 output. In this local source tree, L10 modifies the research image with scripts such as fixImage.sh, inferFile.sh, inferService.sh, and run_service.sh. It may create device nodes, root credentials, NVRAM placeholders, service-launch guesses, and debug listeners.

Therefore:

Booted  -> kernel/userspace startup evidence
ICMP ok -> emulated host reached ICMP
TCP ok  -> at least one scanned TCP/UDP service was observed
port    -> must be mapped to PID and launch source

An open port is a lead. It becomes stronger only after you show the command line came from original firmware logic or you clearly label the synthetic launch conditions.

Hardware Escalation

Hardware is worthwhile when software-only evidence cannot answer a question that materially changes the finding.

Proceed when all are true:

the missing fact is hardware-dependent
the exact board or a meaningfully compatible target is available
the access method is understood and authorized
the result will change the report or next experiment

Use hardware first for:

  • secure boot, fuses, BootROM, trust anchors;
  • external flash/NVRAM not present in an update image;
  • GPIO, sensors, camera pipeline, radio, or USB feature gates;
  • proprietary kernel drivers or MMIO/ioctl security decisions;
  • timing/pairing/state machines that cannot be modeled cheaply.

Do not buy a generic board because the CPU architecture matches. Board wiring, flash layout, boot ROM policy, device tree, peripherals, and vendor drivers are often the claim.

Effort Scoring

Use this synthesized planning score when a lead competes with setup work:

emulation_value =
    3 * importance_of_unknown
  + 2 * probability_the_layer_can_answer_it
  + 2 * reuse_for_other_leads
  + 1 * evidence_quality_gain
  - 2 * setup_cost
  - 2 * peripheral_or_state_uncertainty

Proceed only with a bounded experiment:

time box:
expected observation:
what I will do if it works:
what I will do if it fails:

If the score is negative, keep the lead as a hypothesis and choose a cheaper static or targeted test.

Worked Decisions

Lead Best first method Why Stop condition
Hardcoded credential string Static consumer trace Impact depends on where the credential is used No reachable login/service consumes it
CGI command sink Static route-to-sink, then harness The route and quoting decide exploitability No attacker-controlled parameter reaches the sink
Native parser crash QEMU-user The parser is the object under test Crash requires synthetic-only state unrelated to shipped input
HTTP service appears only after init Service harness or L10 Startup/network context is material Service launch is synthetic and original init does not support it
Firmware update rollback Static updater trace, then full system/hardware Persistence/slot state matters Package cannot be attacker supplied or rollback is enforced
Kernel module ioctl Hardware or kernel-level rehosting Generic userland cannot prove driver/MMIO semantics Module is absent, not loaded, or ioctl is unreachable
MCU RTOS firmware Static plus targeted peripheral model/hardware Peripherals and interrupts dominate Required peripheral state is unknown and not relevant to the finding

Stop Rules

Stop an emulation branch when:

  • it no longer answers the written question;
  • setup consumes the time box without producing new evidence;
  • missing behavior is synthetic and unrelated to the claim;
  • the remaining blocker is hardware-only and out of scope;
  • another lead has a complete input-to-impact chain at lower cost.

Write the stop note:

Attempt:
Evidence gained:
Missing edge:
Why more emulation is not worth it now:
Reopen condition:

Keep that note in the case record. It tells the next researcher exactly what was learned and where confidence ends.