Firmware
Embedded Linux Architecture
ARM
MIPS
Custom ones
Firmware in Embedded Linux
combination of all code running on the device, with many packages:
Bootloader
initializations
HW description
It boots up the kernel image
It passes control to the kernel with pointers to:
info about HW
kernel command line
Kernel
File System
Other resources
Main pentesting activities
Find secrets
backdoor
passwords
API keys
private certificates
Vulnerabilities in binaries
Binaries and Firmware emulation
Creation of a malicious firmware image
Reverse engineering of the binaries
Firmware retrieval
From:
Web
Dump of the device's flash chip
Sniffing of the OTA update
Reverse engineering of mobile application and similar software
Firmware vulnerability analysis
Extract the firmware and look for specific component related security issues
Configuration files and hardcoded secrets
Use
qemuto emulate firmware binaries and firmwareAttach it to a debugger and analyse
Reverse patches and diff two different versions of a firmware
Analyse firmware binaries (
.bin,.img,.pkg,.zip)Run
stringsandhexdumpon them
Extract File System
Manual method
Identify the firmware type
file <firmware_file>
Identify the offset of the file system by grepping the HEX and ASCII stringified firmware by the FS magic number (i.e.
hsqsfor most common file system SquashFS)hexdump -C <firmware_file> | grep -i 'hsqs'
Dump the file system from the firmware
dd if=<firmware_file> bs=1 skip=$((0x<offset>)) of=<output_fs>-
if=<firmware_file>: input file -of=<output_fs>: output file -if: buffer size (1 = 1MB) -skip=$((0x<offset>)): starts from offset0x<offset>
Extract FS files from the FS (e.g. SquashFS)
sudo apt install squashfs-tools unsquashfs <input_fs>
Navigate the File system
cd squashfs-root
Automated method
Extraction with multiple FS support using binwalk
Show different sections
binwalk <firmware_file>Extract the various sections
binwalk -e <firmware_file>Show Entropy (to understand if the firmware is encrypted or not)
binwalk -E <firmware_file>Hex diff betwween two files
binwalk -W <file1> <file2>Recursively extract files from deeply embedded archives
binwalk -Me firmware.bin
Extract protected archive of the firmware with password
fcrackzip -u -b -v <zip_file.zip> -u: unzip-b: brute-force-v: verbose
Encrypted Firmware
Constant entropy for every offset
XOR
Look for the end of the where there are many NULL bytes
hexdump -C <firmware_file> | tail -n 100Look for the identified sequence in the firmware file (e.g.
aa aa aa aa aa aa aa aa)
hexdump -C <firmware_file> | grep -i "aa aa aa aa aa aa aa aa aa"Decrypt the binary using the previous pattern as keys
hexdump -C <firmware_file> | python3 decrypt_firmware.py "aa aa aa aa aa aa aa aa" > decrypted_firmware.bindecrypt_firmware.py
#!/usr/bin/env python3
import sys
# Convert hex string to bytes
key = bytes.fromhex(sys.argv[1])
# Read input as bytes
data = sys.stdin.buffer.read()
# XOR decryption
result = bytearray()
key_len = len(key)
for i, b in enumerate(data):
result.append(b ^ key[i % key_len])
# Write raw binary to stdout
sys.stdout.buffer.write(result)Run binwalk on
decrypted_firmware.bin
Binary emulation
Install
qemusudo apt update sudo apt install qemu-userIdentify the Linux architecture (e.g. ARM, MISP and Endianess)
file <binary_to_be_run>Move to the root folder of the firmware FS
Copy the
qemu-<arch>binary to the current folder to avoid issues when you will change the root folder in the next stepRun the emulator on the binary (e.g.
mips) and change the root folder to the current folder for the emulation (to be sure that dynamic links or references to other programs are working)Big Endian
sudo chroot . qemu-mips <binary_to_be_run>Little Endian
sudo chroot . qemu-mipsel <binary_to_be_run>Debug option (
-g)sudo chroot . qemu-mipsel -g <gdb_port> <binary_to_be_run>

Attach debugger
Launch the program with
qemuand-g <gdb_port>(qemuwill be pending for the connection of the debugger)
gdg-multiarch <binary_file>After launching it:
set architecture type
set architecture mipsset a breakpoint
connect to the remote qemu execution
target remote localhost:<gdb_port>continue
cCategory
GDB Command
Description
Start/Run
gdb ./program
Start GDB with executable
Start/Run
run [args] or r [args]
Run program with optional arguments
Start/Run
start
Run until main() and stop
Start/Run
kill
Stop running program
Start/Run
quit
Exit GDB
Breakpoints
break main or b main
Break at main()
Breakpoints
break file.c:42 or b file.c:42
Break at line 42 of file.c
Breakpoints
break function_name
Break at start of function
Breakpoints
break *0x8048400
Break at specific memory address
Breakpoints
delete [n]
Delete breakpoint number n
Breakpoints
info breakpoints or i b
List all breakpoints
Breakpoints
disable [n] / enable [n]
Temporarily disable/enable breakpoint n
Execution
continue or c
Resume execution until next breakpoint
Execution
next or n
Step over to next line (don’t enter functions)
Execution
step or s
Step into function calls
Execution
finish
Run until current function returns
Execution
until [line]
Run until a specific line
Execution
return [value]
Force current function to return value
Inspect
print var or p var
Print variable value
Inspect
display var
Automatically display variable each step
Inspect
info locals
Show all local variables in current function
Inspect
info args
Show function arguments
Inspect
x/[format] address
Examine memory at address, e.g., x/16xb buf
Inspect
x/[format] $<register_name>
Examine content of register <register_name>
Inspect
info registers or i r
Show CPU registers
Inspect
bt or backtrace
Show call stack
Inspect
frame [n]
Switch to stack frame n
Inspect
up / down
Move up/down the call stack
Watchpoints
watch var
Stop when var changes
Watchpoints
rwatch var
Stop when var is read
Watchpoints
awatch var
Stop when var is read or written
Watchpoints
info watchpoints
List all watchpoints
Watchpoints
delete watch n
Delete watchpoint n
Assembly
set disassembly-flavor intel
Use Intel syntax
Assembly
disassemble [function]
Show assembly for function
Assembly
layout src
TUI mode showing source code
Assembly
layout asm
TUI mode showing assembly
Assembly
layout regs
TUI mode showing registers
Misc
info threads
List all threads
Misc
thread n
Switch to thread n
Misc
set args arg1 arg2
Set program arguments without restarting
Misc
set $<register_name>="VALUE"
Set the value of the register <register_name>
Misc
help
Show GDB help
Misc
help command
Show help for a specific command
Monitor system calls
sudo strace chroot . ./qemu-mips-static <binary_file>Firmware emulation with FAT
Backdooring a firmware
Use Firmware-mod-kit to repack the firmware with changes:
Extract the firmware
Move to firmware-mod-kit folder
Extract the Firmware
sudo extract-firmware.sh <firmware_bin>Access to the results folder
<firmware_name>:
cd <firmware_name><firmware_name>/
├── image_parts/
│ ├── header.img
│ └── rootfs.img
├── logs/
└── rootfs/Compile the C backdoor
Compile the program with a multi-platform compiler Buildroot and move to the folder
make menuconfigSet all the parameters you want (e.g. architectures, external libraries and so on)
Identify the correct compiler in
output/host/usr/bin:
cd output/host/usr/bin
ls -alCompile the program
sudo ./mipssel-builroot-linuxòuclibc-gcc <program>.c -static -o <program>Re-pack the firmware
Move back to firmware-mod-kit folder
Compile the firmware
sudo ./build-firmware.sh -nopad -minMove to the previously created
<firmware_name>folder where you will find the repacked firmwarenew-firmware.bin
<firmware_name>/
├── image_parts/
│ ├── header.img
│ └── rootfs.img
├── logs/
├── new-filesystem.squashfs
├── new-firmware.bin
└── rootfs/Last updated