Firmware Analysis & Emulation: Looking Beyond "Extract and Boot"
Firmware analysis is one of the few areas in offensive security where operating systems, embedded hardware, networking, reverse engineering, filesystems, and Linux internals all collide. This is a practical methodology built from both philosophy and fieldwork.
This blog post is published for research and learning purposes only. It covers firmware analysis and emulation methodology (extraction, mapping, QEMU, and related workflows) for security research and defensive engineering. Apply these techniques only to firmware and devices you are authorised to analyse. Do not use this material to attack third-party products or networks without permission. CyberKartel is not responsible for misuse of the information in this article.
Most guides follow the same pattern:
Download firmware → run Binwalk → extract filesystem → launch QEMU → access web interface.
It looks clean. Reality rarely is.
Real firmware analysis is not a single command. It is a sequence of decisions: identify the image, unpack it correctly, map its assumptions, emulate only the meaningful part, repair the environment carefully, then use static and dynamic analysis together. The goal is not to make a device "fully boot" in a perfect virtual clone. The goal is to understand the firmware well enough to reach the parts that matter: web interfaces, daemons, update logic, configuration handling, and any code paths that may hide security flaws.
Firmware Is Not an Operating System
One of the biggest misconceptions is treating firmware like a Linux distribution.
Firmware is software built specifically for hardware with a predefined purpose.
A consumer router doesn't need:
- desktop services
- package managers
- user sessions
- unnecessary daemons
Instead, it usually contains only what the hardware requires:
- Linux kernel
- Bootloader
- Root filesystem
- Hardware drivers
- Vendor applications
- Configuration storage
Every byte matters because flash storage, RAM, and CPU power are limited.
This design philosophy changes how analysts should approach firmware. Instead of asking:
"How do I boot this?"
Ask:
"What hardware assumptions was this firmware built around?"
That single question saves hours of frustration. Once you start following dependencies instead of memorizing commands, firmware stops looking like a mysterious black box. It becomes an engineered system with assumptions, constraints, and logic that can be understood, modeled, and ultimately tested.
Beginners often search for vulnerabilities immediately. Experienced researchers search for architecture first.
Step 1 — Identify the Image, Not Attack It
Before extraction, look at the firmware as a packaged system. The first pass usually answers:
- What architecture is this built for?
- Is it Linux-based, or something else?
- Is the image compressed, encrypted, or split into multiple partitions?
- Does it contain a kernel, root filesystem, bootloader, or only one of these?
This step sounds basic, but it decides the whole workflow. A MIPS little-endian image, an ARM image, and a full NAND dump are not handled the same way. If you skip this, you end up fighting the tool instead of the firmware.
A practical first triage means checking file type, strings, header data, and partition layout. If the image is a vendor update package, unpack that first. If it is a raw flash dump, identify the filesystem boundaries before trying to mount anything.
Beginners often search for vulnerabilities immediately. Experienced researchers search for architecture first.
Before touching Ghidra or IDA, identify:
- CPU architecture
- Endianness
- Filesystem type
- Compression scheme
- Bootloader
- Init process
- Network configuration
- Vendor-specific services
These components describe the firmware's ecosystem. The binary you're interested in is only one piece of a much larger system.
Architecture identification is mandatory. A MIPS little-endian image, an ARM image, and a full NAND dump are not handled the same way. If you skip this step, you end up fighting the tool instead of the firmware.
Step 2 — Extract in Layers, Not All at Once
Firmware is usually nested. One archive contains another. One partition contains compressed data. One filesystem contains vendor binaries and init scripts. Extraction works best when treated like peeling layers.
The common mistake is to run one extractor and assume the job is done. The better approach is:
- Identify the outer container.
- Unpack it.
- Inspect the result.
- Repeat until you reach filesystem content.
This matters because a large part of firmware analysis is not the final firmware image itself, but the structure around it. Vendor scripts, board-specific configuration files, init systems, and startup binaries often reveal more than the web server people want to reverse.
At this stage, focus on identifying the runtime environment:
initscripts- startup order
- web server binaries
- custom RPC services
- NVRAM or config references
- hardcoded paths
- device model checks
- board identifiers
That information tells you what the firmware expects at runtime.
Step 3 — Map the Runtime Assumptions
Once extracted, the next task is not emulation. It is environment mapping.
Every firmware image assumes things that do not exist in a plain QEMU boot. It expects flash partitions, specific interfaces, config storage, board names, and sometimes vendor services. That is why many people hit a boot failure and immediately assume the image is broken. Usually it is not broken. It is just missing the surroundings it was written for.
A practical analysis should answer:
- What does
/etc/init.d/start? - What binary launches the web interface?
- Where are configuration values stored?
- Does the firmware read from
/proc,/sys, NVRAM, or custom device nodes? - Which services need network access to function?
This is where the image starts becoming a system instead of a file dump.
Focus on the target. Full system emulation is not always the right target. In many cases, you only need one service: a web server, a command parser, an update handler, or a network daemon.
Step 4 — Emulate the Service You Actually Need
Full system emulation is not always the right target. In many cases, you only need one service: a web server, a command parser, an update handler, or a network daemon.
This is where experienced work diverges from beginner work. A beginner tries to boot everything. A practical analyst asks:
"Which component gives me the most value with the least effort?"
- If the web UI is the target, bring up the web stack first.
- If the service listens on a socket, trace that path first.
- If authentication or config parsing is the interesting part, emulate just enough of the environment for that binary to run.
This reduces noise and speeds up analysis. It also makes debugging saner, because you are testing one component, not an entire imaginary appliance universe.
The objective is reproducing behaviour, not simply booting an operating system.
Depending on your research, successful emulation may mean:
- a web server responding correctly
- an RPC service accepting requests
- UPnP functioning
- TFTP daemon running
- a proprietary protocol active
- a vulnerable service processing packets
If the target service behaves like the physical device, your emulation has already achieved its purpose. Everything else is optional.
Step 5 — Perfect Emulation Doesn't Exist; Fix What's Missing
Every embedded device depends on hardware:
- GPIO
- NVRAM
- Flash partitions
- EEPROM
- Wi-Fi chipsets
- Ethernet switches
- LEDs
- Watchdogs
- Vendor ASICs
QEMU can emulate CPUs remarkably well. It cannot magically recreate proprietary hardware.
This is why you frequently encounter errors such as:
These are often indicators of missing hardware rather than broken firmware. Understanding this distinction changes debugging completely.
Real emulation is mostly repair work. The trick is not to guess wildly — it is to patch the environment in the smallest possible way and verify each change.
- missing libraries
- missing symlinks
- missing config files
- missing
/devnodes - unsupported mount points
- hardcoded paths
- init dependencies
- interface assumptions
- invalid board checks
This is normal. The trick is not to guess wildly. It is to patch the environment in the smallest possible way and verify each change:
- Change one thing.
- Test one service.
- Confirm one result.
That is how emulation becomes reliable instead of theatrical.
Many firmware projects fail not because of QEMU. They fail because networking wasn't understood. A router firmware assumes packets arrive exactly as they would on real hardware.
Networking Is the Hidden Requirement
Many firmware projects fail not because of QEMU. They fail because networking wasn't understood.
Firmware expects:
- bridges
- VLANs
- TAP interfaces
- ARP
- routing
- NAT
- multiple Ethernet ports
- switch chips
A router firmware assumes packets arrive exactly as they would on real hardware. If the virtual network isn't designed correctly, researchers often blame QEMU when the issue actually lies in the network topology.
Ironically, embedded security frequently becomes a networking exercise.
Disassemblers are powerful. But they should not be the first tool. Simple Linux utilities often answer critical questions faster.
Reverse Engineering Starts Before Opening Ghidra
Disassemblers are powerful. But they should not be the first tool.
Simple Linux utilities often answer critical questions faster:
filereadelfstringsobjdumplddchecksecreadlink
Within minutes you can determine:
- architecture
- compiler
- linked libraries
- PIE status
- RELRO
- NX
- RPATH
- interpreter
- debug symbols
Knowing these beforehand makes reverse engineering significantly more efficient.
Static Guides Dynamic
Static analysis tells you where to look. Dynamic testing tells you what the code really does.
Jump into strings, import tables, function names, and configuration references before opening a disassembler. Those clues identify the high-value binaries. After that, Ghidra or IDA becomes much more efficient because the target is already known.
During dynamic analysis, watch for:
- request handling flow
- authentication checks
- file reads and writes
- command execution
- environment variable use
- IPC or socket behaviour
- parsing bugs
- unsafe system calls
Static analysis alone gives suspicion. Dynamic analysis gives proof.
Static analysis tells you what could happen. Dynamic analysis shows what actually happens. When firmware runs, new observations become possible — process creation, IPC communication, HTTP requests, socket behaviour, memory allocation, filesystem modifications, configuration parsing, authentication flow. Sometimes a vulnerability isn't obvious in disassembly. Watching the application execute reveals it immediately.
Static guides dynamic. Jump into strings, import tables, function names, and configuration references before opening a disassembler. Those clues identify the high-value binaries.
The Goal Isn't Exploitation
Many newcomers believe firmware research ends with finding a CVE.
In reality, exploitation is often the final step.
The real value lies in understanding:
- why the vulnerability exists
- how trust boundaries failed
- why developers believed the design was safe
- what assumptions the hardware enforced
- whether the issue survives outside laboratory conditions
Good researchers don't simply find bugs. They understand systems.
The real value lies in understanding why the vulnerability exists, how trust boundaries failed, and whether the issue survives outside laboratory conditions.
Document the Firmware Like a System, Not a Sample
A useful firmware note is not just "this binary exists." It is:
- what the device is
- what architecture it uses
- what the main partitions contain
- which service was emulated
- what had to be patched
- what failed and why
- which files matter for further analysis
That record is what turns one-off investigation into repeatable methodology. Without it, every new firmware starts from zero — a fine way to make your own life worse for no reason.
Document like a system, not a sample. A useful firmware note includes: what the device is, what architecture it uses, what the main partitions contain, which service was emulated, what had to be patched, what failed and why, and which files matter for further analysis.
Final Thoughts
Firmware analysis teaches something surprisingly valuable:
Computers are not magical.
Every layer depends on the one beneath it:
- Every service depends on hardware
- Every binary depends on an operating system
- Every operating system depends on a kernel
- Every kernel depends on architecture
- Every architecture depends on silicon
The tools will continue to evolve. QEMU will improve. New architectures will appear. Vendors will introduce new protections.
But the mindset remains constant:
Don't begin by asking: "How do I emulate this firmware?"
Begin by asking: "What environment does this firmware expect to exist?"
That question is usually the difference between spending ten minutes solving a problem and spending two days fighting an error message that was never really an error.
Humanity does enjoy blaming the screwdriver when the blueprint is upside down. Embedded devices are less dramatic. They simply expect the world they were built for.
The point is not to make firmware "look like Linux."
The point is to make the firmware reveal how it actually works.