Date: 2026-05-25
Use this file during the assignment.
If the simple path breaks, use research-algorithms.md to choose the next experiment and field-manual.md as the challenge index. Use reference-guide.md as the long reference manual.
Produce one defensible vulnerability path:
reachable input -> vulnerable code path -> reproducer -> impact/exploitability -> limitations
Do not submit scanner output as the finding.
Use these evidence states while working:
lead -> hypothesis -> confirmed root cause -> demonstrated impact
A CVE, unsafe function, open port, version string, AI note, or EMBA result starts as a lead. Promote it only when the missing edge is proven.
Default:
Windows host
-> VMware Workstation Pro
-> Kali VM with EMBA classic Docker mode
-> optional Ubuntu 24.04.4 LTS VM only as no-EMBA backup/manual workbench
If Kali/EMBA works, stay on that path. Use Windows GUI tools for IDA/Ghidra and notes.
Weak host with 4 logical cores:
VM: 2 vCPU
RAM: 6-12 GB depending on host RAM
Run only one VM at a time
Run IDA/Ghidra GUI on Windows host
Avoid heavy full-system emulation
Remote fallback:
Rent strong EC2 Ubuntu host
Run tools directly over SSH
Use Firecracker only later if you need many isolated workers
Create a run folder:
mkdir -p runs/fw1/artifacts
cd runs/fw1Record metadata:
sha256sum /path/to/firmware.bin | tee 01_sha256.txt
file /path/to/firmware.bin | tee 02_file.txt
binwalk /path/to/firmware.bin | tee 03_binwalk.txtExtract:
binwalk -eM /path/to/firmware.bin
find . -maxdepth 4 -type f | tee artifacts/file_tree.txtIf Binwalk fails and Kali/EMBA works, try EMBA quick scan:
cd ~/tools/emba
sudo ./emba -l ~/emba_logs/fw1/quick_scan \
-f /path/to/firmware.bin \
-p ./scan-profiles/quick-scan.embaIf Kali/EMBA/Docker is blocked, use ../lab-setup/ubuntu-no-emba-backup-guide.md instead of spending the assignment on setup.
Before grepping for bug patterns, build a small graph:
startup/config -> listener or scheduled job -> input -> parser/transform -> sink -> effect
For each row, record the process user, default or feature-gated state, attacker position, and cheapest test that could confirm reachability. Use research-algorithms.md when several components compete.
Find services and web roots:
rg -n "httpd|lighttpd|boa|uhttpd|telnetd|dropbear|sshd|upnp|miniupnp|cgi-bin" .
find . -type d \( -name "www" -o -name "htdocs" -o -name "cgi-bin" \)
find . -type f \( -name "*.cgi" -o -name "*.sh" -o -name "*.lua" -o -name "*.php" \)Find high-ROI bug patterns:
rg -n "system\(|popen\(|exec|eval|wget|curl|tftp|nc |/bin/sh|sh -c" .
rg -n "password|passwd|secret|token|key|admin|root" .
rg -n "\.\./|realpath|fopen|open\(|readfile|download|upload" .
rg -n "firmware|upgrade|update|signature|md5|sha1|openssl" .
rg -n "ubi|ubifs|jffs2|/mnt/jffs2|/overlay|/dev/mtd|/proc/mtd|fw_printenv|factory|caldata|Config|Env|Storage" .
rg -n "uart|rs232|rs-232|jtag|swd|spi|i2c|can|socketcan|usb|uboot|u-boot|uefi|initramfs|failsafe|recovery|otp|efuse|secure boot|root of trust|plc|modbus|profinet|ethercat|bacnet" .Research-derived shortcuts:
- Start from default-started services and update clients. Synacktiv's Netgear R6700v3 work turned a background update daemon into the main finding.
- Map web routes to parsers before reversing deeply. Claroty's Synology BC500 writeup moved from firmware layout to web config to CGI parser.
- Treat logging strings and source-like function names as anchors. SpaceRaccoon's Tapo C260 writeup used logging/source functions to find request handlers fast.
- Record feature preconditions. NCC's BrokenPrint finding depended on ReadySHARE being reachable only when a USB printer was connected.
Use the complete-chain test before choosing by bug class:
reachable entry point
-> attacker-controlled value
-> vulnerable operation or trust decision
-> safe observable effect
If one edge is missing, write it as a hypothesis and identify the cheapest test for that edge. Prioritize a reachable lower-impact lead over an isolated high-impact sink.
Prefer:
- command injection in CGI/API/script
- path traversal
- hardcoded credential with reachable service
- auth/session flaw
- insecure update path
- controlled crash in exposed parser
Reject weak candidates:
- version-only CVE with no reachable path
- hardcoded string with no service/login path
- crash with no input control
- AI claim with no code evidence
High-ROI choice rule:
Pick the lead with a complete chain: startup/config -> reachable route/service -> attacker-controlled field -> sink/parser -> safe proof.
This is the common pattern across Claroty's router/camera chain, Neodyme's Netgear work, and Talos' WAGO cloud-to-device research. A less severe bug with a full chain is usually better than a scarier sink with no reachable input.
Write the question emulation must answer before starting it. Examples include “does the route reach this handler?” and “does the parser accept this field?” Use research-algorithms.md to estimate whether QEMU-user, a service harness, full-system emulation, or hardware is justified.
When using EMBA, consult the source-code capability map before interpreting a boot, port, NVRAM, dependency, or version result. It lists the image repairs and synthetic launch paths that can change the meaning of a successful emulation.
Start with user-mode, not full-system emulation.
Exception: if the lead is a missing secret, account, generated key, calibration
value, or config value and the firmware references raw flash storage, check
field-manual.md before spending
time on generic full-system emulation. A Gemtek-style full NAND dump with known
geometry and a UBI/JFFS2 mount such as /mnt/jffs2 may justify MTD/UBI
reconstruction; a rootfs-only password helper usually does not.
Find architecture:
file rootfs/bin/busybox
file rootfs/usr/sbin/httpdExample:
sudo apt install -y qemu-user-static gdb-multiarch strace
cp /usr/bin/qemu-mipsel-static rootfs/usr/bin/
sudo chroot rootfs /usr/bin/qemu-mipsel-static /bin/busyboxIf full emulation fails, document the blocker and continue with static reachability.
Research-derived emulation rule:
- Emulate the smallest thing that answers the question. SpaceRaccoon's Nokia Beacon 1 used Qiling for one password-generation path, not the whole router.
- Compare manual QEMU against framework output when services do not start, as in Applied Security's IoT Firmware Emulation with Qemu.
- If hardware-dependent emulation fails, pivot to static proof and record the blocker. Neodyme's HP M479fdw writeup is the model.
EMBA-specific evidence rule:
S115 proves one-binary behavior in a copied/repaired test root.
L10 proves behavior in a modified generic emulation image.
F17/F50 prioritize CVEs and exploits; they do not prove reachability.
Before relying on an EMBA port or service result, map the port to a PID, command line, and launch source, then check whether it came from original init logic or EMBA inference/debug helpers.
For web bugs:
curl -i "http://127.0.0.1:8080/"
curl -i "http://127.0.0.1:8080/cgi-bin/target?param=test"For safe command injection proof:
Use echo/id/sleep only.
Do not run destructive commands.
Prefer timing proof if output is hidden.
For path traversal:
curl -i "http://127.0.0.1:8080/download?file=../../etc/passwd"For binary crash:
qemu-mipsel-static -g 1234 -L rootfs rootfs/usr/sbin/target args
gdb-multiarch rootfs/usr/sbin/targetBefore claiming impact, write the preconditions:
network side, auth state, service enabled by default or feature-gated, required hardware/config, process user, and whether restart/retry behavior matters
# Firmware Vulnerability Research Report
## Scope
- Firmware:
- SHA256:
- Constraints:
## Executive Summary
- Finding:
- Impact:
- Confidence:
## Environment
- Host/VM:
- Tools:
- Limitations:
## Attack Surface
- Architecture:
- Services:
- Web/API routes:
## Finding
### Reachability
- Endpoint/service:
- Startup path:
- Input parameter:
### Root Cause
- File/function/address:
- Vulnerable operation:
- Why validation fails:
### Reproducer
- Command/request:
- Observed result:
### Exploitability
- Attacker control:
- Privileges/context:
- Realistic exploitation path:
- Constraints:
### Fix
- Validate/quote inputs
- Avoid shell
- Canonicalize paths
- Add auth/signature checks
## AI Usage
- Where AI helped:
- What was manually verified:
- False positives:0-2h: hash, identify, extract
2-5h: services, web roots, grep patterns
5-8h: choose one candidate
8-14h: inspect code and try user-mode/chroot
14-22h: build reproducer
22-30h: root cause and exploitability
30-40h: write report
40-48h: rerun commands and polish evidence
- full-system emulation before static triage
- Firecracker for a one-off assignment
- FACT unless already installed
- broad fuzzing without a target
- reporting CVEs from versions only
- letting AI decide exploitability
For a fuller stop rule and hardware decision gate, see research-algorithms.md.
If hardware or boot-access evidence appears, classify it before celebrating:
UART/RS-232: log, login, root shell, bootloader shell, or initramfs shell?
SPI/eMMC: firmware, env, config, factory data, calibration, or logs?
JTAG/SWD: boundary scan, CPU debug, flash access, or locked?
CAN/I2C/USB: which firmware driver or process consumes the traffic?
OT: what lab/simulator state makes proof safe?
Use field-manual.md for the evidence checklist and stop rules.
Setup/tool reference index: reference-guide.md
Real-world challenge map: field-manual.md