Skip to content

Firmware Reverse Engineering

Loading bare-metal binaries into IDA

Requirements:

  • The load address is the address in memory that the binary is being executed from.
  • The entry point is the location within the binary where the processor starts executing.

⚠️ For ARM Arduino firwmare the entry point is located at _RESET interruption.

To load it properly in IDA, open the file, select ATMEL AVR and then select ATmega323_L.

Loading bare-metal binaries into Radare2

Radare2 can disassemble avr, arduino natively

$ radare2 -A -a arm -b 32 ihex://Challenge_v3.hex
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] find and analyze function preludes (aap)
[x] Analyze len bytes of instructions for references (aar)
[x] Check for objc references
[x] Check for vtables
[x] Finding xrefs in noncode section with anal.in=io.maps
[x] Analyze value pointers (aav)
[x] Value from 0x00000000 to 0x10001018 (aav)
[x] 0x00000000-0x10001018 in 0x0-0x10001018 (aav)
[x] Emulate code to find computed references (aae)
[x] Type matching analysis for all functions (aaft)
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.

[0x565e8640]> aaaa
[0xf7723a20]> afl
[0xf7723a20]> e asm.describe = true
[0xf7723a20]> s main
[0x0804873b]> pdf

To perform a case-insensitive search for strings use /i:
[0x0001d62c]> /i Exploding
Searching 9 bytes in [0x0-0x10001018]
hits: 1
0x0003819e hit1_0 .. N# NExploding Firmware ! N.

$ r2 -a avr /tmp/flash
[0x000000c4]> afr
[0x000000c4]> pd 17

$ rasm2 -a avr -d "0c94 751b 0c94 9d1b 0c94 d72c" 
jmp 0x36ea
jmp 0x373a
jmp 0x59ae

Loading bare-metal binaries into Ghidra

SVD-Loader for Ghidra automates the entire generation of peripheral structs and memory maps for over 650 different microcontrollers

  • SVD-Loader for Ghidra: Simplifying bare-metal ARM reverse engineering - svd-loader/

Usage

  • Load a binary file
  • Open it in the code-browser, do not analyze it
  • Run the SVD-Loader Script
  • Select an SVD file
  • Analyze the file

ESPTool

ESP8266 and ESP32 serial bootloader utility : espressif/esptool

josh@ioteeth:/tmp/reversing$ ~/esptool/esptool.py image_info recovered_file
esptool.py v2.4.0-dev
Image version: 1
Entry point: 4010f29c
1 segments
Segment 1: len 0x00568 load 0x4010f000 file_offs 0x00000008

nRF5x Firmware disassembly tools

$ python3 nrfident.py bin firmwares/s132.bin
Binary file provided firmwares/s132.bin
Computing signature from binary
Signature:  d082a85351ee18ecfdc9dcb01352f5df3d938a2270bcadec2ec083e9ceeb3b1e
=========================
SDK version:  14.0.0
SoftDevice version: s132
NRF: nrf52832
=========================
SDK version:  14.1.0
SoftDevice version: s132
NRF: nrf52832
SoftDevice  :  s132
Card version :  xxaa
           *****
RAM address  :  0x20001368
RAM length   :  0xec98
ROM address  :  0x23000
ROM length   :  0x5d000

Pure disassemblers

  • Vavrdisasm -- vAVRdisasm will auto-recognize Atmel Generic, Intel HEX8, and Motorola S-Record files - vsergeev/vavrdisasm
  • ODA - The Online Disassembler
  • avr-objdump – gcc kit standard tool

    $ avr-objdump -l -t -D -S main.bin > main.bin.dis
    $ avr-objdump -m avr -D main.hex > main.hex.dis
    

Simulating AVR

Programs compiled for Arduino can be simulated using AVR Studio or the newer Atmel Studio. I have used the former along with hapsim. Hapsim works by hooking into AVR Studio and can simulate peripherals like the UART, LCD etc.

$ simulavr -P atmega128 -F 16000000 f build-crumbuino128/ex1.1.elf

UEFI Firmware

Parse BIOS/Intel ME/UEFI firmware related structures: Volumes, FileSystems, Files, etc - theopolis/uefi-firmware-parser

sudo pip install uefi_firmware
$ uefi-firmware-parser --test ~/firmware/*
~/firmware/970E32_1.40: UEFIFirmwareVolume
~/firmware/CO5975P.BIO: EFICapsule
~/firmware/me-03.obj: IntelME
~/firmware/O990-A03.exe: None
~/firmware/O990-A03.exe.hdr: DellPFS

References