The Ghost in the Machine: Reverse Engineering Firmware in Legacy Infrastructure
The Ghost in the Machine: Reverse Engineering Firmware in Legacy Infrastructure
Legacy infrastructure rarely fails because of one dramatic flaw. It fails because undocumented code keeps making decisions inside devices nobody has updated in years. A substation relay, a programmable logic controller, a rail signalling module, a building automation gateway, or a water-treatment remote terminal unit may run for decades with the same firmware image loaded at commissioning. The vendor may have merged, discontinued the product, or lost the original source. The device still works, so replacing it feels risky. Then a vulnerability appears, a protocol breaks, a certificate expires, or a maintenance team needs to understand why the unit behaves differently from the manual. That is where firmware reverse engineering becomes practical engineering rather than academic curiosity. It is the discipline of extracting, analyzing, and understanding embedded software from hardware whose design intent is partly or completely unavailable. In legacy infrastructure, the goal is usually not to copy functionality. The goal is to answer operational questions: What does this device actually do? How does it authenticate? What protocol assumptions does it make? Can it be patched? Can it be safely segmented? What happens if an input goes out of range?
Why Legacy Firmware Becomes a Risk
Industrial and infrastructure devices are built for long service lives. A protection relay installed in 2008 may still be expected to run in 2035. A PLC family introduced in the late 1990s may control pumps, turbines, conveyors, gates, and substations long after its vendor considers it obsolete. That creates a mismatch between asset lifespan and software security assumptions. Many older firmware images were written for networks considered isolated. Common design patterns included:
- Hardcoded service credentials
- Unsigned firmware updates
- Serial debug consoles left enabled
- Cleartext fieldbus or TCP protocols
- Proprietary authentication based on obscurity
- No address-space randomization or modern exploit mitigations
- Shared firmware across product variants with dormant features left compiled in
These choices were not always negligent at the time. A serial-connected controller behind locked doors faced different threats than an Ethernet-enabled device reachable through a flat plant network. The problem is that infrastructure networks changed. Remote maintenance, historian integration, cellular gateways, cloud dashboards, and vendor support tunnels widened the attack surface. Reverse engineering helps expose the real behaviour of devices that documentation describes only partially.
What Counts as Firmware
Firmware sits between hardware and user-facing software. It initializes chips, reads sensors, drives outputs, handles communications, enforces control logic, and stores configuration. In legacy infrastructure, firmware may exist in several places:
- NOR flash connected to a microcontroller
- NAND flash used by an embedded Linux system
- EEPROM storing boot configuration and calibration data
- FPGA bitstreams loaded at startup
- ROM inside an older microcontroller
- Firmware update files from vendor support portals
- CompactFlash, SD, or IDE storage in industrial PCs
- Option-card firmware separate from the main controller
A single rack-mounted automation unit might contain a bootloader on SPI flash, an RTOS application in parallel NOR, configuration in I²C EEPROM, and protocol firmware on a communication daughterboard. Treating the device as one black box usually misses key details.
Acquiring the Firmware Image
Analysis starts with acquisition. The cleanest path is a vendor update package, but legacy infrastructure often requires hardware extraction.
Vendor Update Files
Firmware update packages may contain raw binary images, compressed archives, encrypted payloads, or container formats with headers and checksums. Even when encrypted, metadata can reveal model identifiers, CPU architecture, version strings, build dates, and partition layouts. Tools such as binwalk, file, strings, xxd, and hexdump can quickly identify compression formats, filesystems, and embedded certificates. A 16 MB update file may contain a bootloader, Linux kernel, SquashFS root filesystem, and application partition in sequence.
Debug Interfaces
Many boards expose JTAG, SWD, UART, or vendor-specific service headers. On older industrial equipment, these pins are sometimes unpopulated but still routed to test pads. A UART console at 115200 baud can reveal boot logs, kernel command lines, memory maps, and shell access. JTAG may allow memory dumping or CPU halt control. SWD can extract flash from ARM Cortex-M devices if readout protection is not enabled. Finding the interface requires board inspection, continuity testing, datasheet research, and sometimes logic analysis. A 10-pin header near an ARM microcontroller is a clue, not proof.
Direct Flash Extraction
If software access is blocked, the flash chip itself can be read. SPI NOR chips are common and can often be dumped in-circuit with a clip, though surrounding components may interfere. Parallel NOR, NAND, and eMMC usually require more care. Forensic discipline matters. Record chip markings, board revision, voltage levels, tool versions, checksums, and every modification. In infrastructure environments, the ability to reproduce and defend the acquisition method is as important as the binary itself.
Live Memory Capture
Some secrets never appear plainly in flash. A device may decrypt firmware into RAM, load protocol keys at boot, or unpack compressed code into executable memory. Live memory extraction through JTAG, kernel interfaces, or bootloader commands can reveal runtime state. This is especially relevant for devices using encrypted update packages but no hardware root of trust. The firmware may be protected in transit yet exposed after boot.
Identifying Architecture and Layout
A raw binary is just bytes until structure appears. First, analysts look for CPU architecture. Instruction patterns, interrupt vector tables, endianness, reset addresses, and known boot headers provide clues. Legacy infrastructure may use ARM, PowerPC, MIPS, 8051, Renesas H8, ColdFire, Infineon TriCore, AVR, or proprietary DSP cores. A Cortex-M image often starts with an initial stack pointer followed by a reset vector. MIPS firmware may show recognizable prologues and branch delay slots. PowerPC code has distinctive fixed-width instructions and frequent use in older industrial and networking equipment.
Next comes memory mapping. Embedded firmware often assumes absolute addresses. Code may be linked for flash at 0x08000000, RAM at 0x20000000, memory-mapped registers at 0x40000000, and external peripherals at board-specific ranges. Loading a binary at the wrong base address in Ghidra or IDA Pro creates misleading disassembly. Useful artifacts include:
- Vector tables
- Bootloader headers
- ASCII strings
- Version banners
- Filesystem superblocks
- Compression signatures
- Function pointer tables
- Interrupt handler references
- Memory-mapped I/O constants
Once the architecture and base addresses are correct, the firmware starts to look less like noise and more like a program.
Static Analysis: Reading Behaviour Without Running It
Static analysis examines code, data, and structure without executing the firmware. For embedded Linux devices, the root filesystem is often the easiest starting point. Configuration files may expose startup scripts, web server routes, SNMP community defaults, SSH settings, writable directories, and update logic. Binaries can be imported into Ghidra, IDA Pro, Binary Ninja, or radare2 for disassembly and decompilation.
For RTOS or bare-metal firmware, the work is more manual. There may be no file system, no symbols, and no process boundary. The analyst reconstructs functionality by naming functions, tracking hardware register access, identifying protocol parsers, and mapping interrupts to behaviour. Strings are powerful but incomplete. A string such as AUTH FAILED may lead to an authentication routine. A Modbus function code table may reveal protocol handling. A hidden command like factory_enable may expose maintenance behaviour. Yet optimized firmware may inline logic, strip symbols, compress strings, or build messages dynamically. Static analysis can answer questions such as:
- Does the device verify firmware signatures?
- Are credentials hardcoded or derived?
- Is the web interface vulnerable to command injection?
- How are firmware update packages parsed?
- Which services are enabled by default?
- Does the protocol parser enforce length checks?
- Are safety interlocks implemented in firmware or external hardware?
In infrastructure settings, that last question matters. A software bypass is very different from a relay contact physically wired into a shutdown circuit.
Dynamic Analysis: Watching the Device Think
Dynamic analysis observes firmware while it runs. This can mean executing the firmware in an emulator, instrumenting the real hardware, or interacting with a lab device under controlled conditions.
Emulation
For Linux-based firmware, QEMU user-mode or full-system emulation can run services outside the original device. This is useful for testing web interfaces, update handlers, and protocol daemons. Tools such as Firmadyne, FAT, and custom QEMU setups help recreate network behaviour. Emulation is harder for bare-metal controllers because firmware expects exact peripherals, timers, interrupts, ADCs, and memory-mapped registers. Missing hardware can cause boot loops or dead code paths. Still, partial emulation can execute parsers or cryptographic routines once dependencies are stubbed.
Hardware-in-the-Loop
For PLCs, relays, and RTUs, hardware-in-the-loop testing is often more reliable. The device is powered in a lab, connected to simulated inputs, and monitored with serial logs, logic analyzers, oscilloscopes, packet captures, and debug probes. A test rig might replay DNP3, Modbus TCP, IEC 60870-5-104, BACnet, or proprietary vendor traffic while monitoring relay outputs and internal logs. The point is not just to crash the device. It is to determine whether malformed packets affect control behaviour, timing, fail-safe states, or recovery.
Instrumentation
Instrumentation can be as simple as adding UART logging or as complex as patching firmware to trace function calls. Analysts may modify conditional branches, insert breakpoints, hook protocol handlers, or redirect output to unused pins. Patching must be done carefully. A patched safety device is no longer equivalent to the fielded device. For vulnerability research and behaviour mapping, document every patch and avoid drawing operational conclusions from modified code unless the change is proven irrelevant to the behaviour being studied.
The Hard Parts Specific to Infrastructure
Legacy infrastructure firmware differs from consumer firmware in several ways. First, failure modes are physical. A router crash causes downtime. A controller crash may stop a pump, open a breaker, disable cooling, or trigger a process trip. Lab isolation is mandatory. Second, timing matters. Some devices depend on deterministic scan cycles, watchdogs, and interrupt latency. Instrumentation that adds milliseconds of delay can change behaviour. Third, firmware may include calibration and site-specific logic. Two devices with the same model number may not be interchangeable because EEPROM contains analog calibration constants, relay settings, or plant-specific configuration. Fourth, protocols are often old, custom, or extended. A vendor may implement Modbus with private function codes, serial framing quirks, or undocumented diagnostic modes used by field technicians. Fifth, patching is constrained. Even if a vulnerability is understood, there may be no supported update path. The device may require downtime, physical access, certification review, or regression testing against safety requirements.
Security Findings That Matter Most
Not every bug has the same operational weight. In legacy infrastructure, the most useful findings are tied to realistic paths and clear mitigations. High-value findings include:
- Authentication bypass on engineering interfaces
- Unsigned or weakly verified firmware updates
- Hardcoded private keys or passwords shared across devices
- Remote code execution in always-on network services
- Denial-of-service bugs affecting control availability
- Hidden maintenance commands reachable over field networks
- Unsafe fail-open behaviour after malformed input
- Configuration extraction that exposes process details
- Weak cryptography protecting remote access sessions
A report should state prerequisites precisely. “Remote unauthenticated attacker on TCP port 502 can crash the communication task with a single malformed packet” is useful. “Device may be insecure” is not. The best reverse engineering work produces artifacts operators can act on: firewall rules, compensating controls, detection signatures, firmware version fingerprints, update validation steps, and safe replacement plans.
Legal, Safety, and Operational Boundaries
Firmware reverse engineering in critical or legacy infrastructure requires authorization and scope control. The same technical methods can support maintenance, assurance, incident response, or misuse. Written authorization, asset identification, lab isolation, and chain-of-custody records are not paperwork burdens. They protect the work and the people relying on it. Never test unknown payloads against production control equipment. Do not assume a duplicate device from a warehouse contains the same configuration as the field unit. Do not publish exploit details for unsupported infrastructure without a coordinated disclosure plan and practical mitigations. Safety engineers, operators, and maintenance technicians should be part of the process. They know which outputs matter, which alarms are noisy, which resets are dangerous, and which “u
Comments
No comments yet. Start the discussion.