Firmware Acquisition: U-Boot

From Embedded Lab Vienna for IoT & Security
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Summary

This article briefly describes how the U-Boot bootloader can be used to extract the firmware from embedded devices. This method involves the use of the Universal Synchronous Asynchronous Receiver and Transmitter (USART) On-Chip Debug (OCD) Interface. This article is currently limited to md (memory dump) but will be extended soon. In the end, md is the method which is extremly slow but work in most scenarios.

Requirements

  • Basic understanding of U-Boot and UART
  • Taget Device using the U-Boot bootloader
  • Serial UART line ready between Target and Analyst
  • Access to the U-Boot command line interface

Procedure

Note: Not all of these methods may be applicable depending on the present U-Boot version.

Memory Dump

The md command can be used to display memory contents both as hexadecimal and ASCII data. (UBootCmdMd) The md method can be used to extract the firmware via UART, by dumping the complete or a distinct memory space. In the following the ISmartAlarm® ISC5 SPOT IP-Camera will be used as example using screen to save the memory dump to a log file. In this example, screen /dev/tty.usbserial-1410 115200 was used to access the TTY and the CTRL-a H (log) key binding has been used to start logging of the current window to the file "screenlog.n". (See: man screen). So, after the serial line and logging is ready, the memory layout must be identified. This is possible using the mtdparts, devinfo or printenv command (and more) if available or through identification of the chip and calculating the memory space based on the chip's capacity. Alternaively the mtdparts may be printed in the bootlogs or can be accessed if access to a Linux shell has already been acquired via /proc/mtdparts

=> help md
md - memory display

Usage:
md [.b, .w, .l] address [# of objects]
ⓘ Example: ISmartAlarm® ISC5 SPOT IP-Camera - U-Boot commands
sonix # version
U-Boot 2011.09 (May 22 2015 - 16:07:40)
arm-linux-gcc (SONiX GCC-4.5.2 Release 2011-12-06) 4.5.2
GNU ld (GNU Binutils) 2.22

sonix # ?
?       - alias for 'help'
bdinfo  - print Board Info structure
boot    - boot default, i.e., run 'bootcmd'
bootm   - boot application image from memory
cmp     - memory compare
cp      - memory copy
crc32   - checksum calculation
devinfo - devinfo
dump    - dump image
erase   - erase FLASH memory
eraseetc- eraseetc
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls   - list files in a directory (default /)
fatupdate- update firmware from fat32 filesystem
flinfo  - print FLASH memory information
go      - start application at address 'addr'
help    - print command description/usage
hwcrc16 - hwcrc16 - hardware crc16 calculate
loadb   - load binary file over serial line (kermit mode) and update to flash
loadkernel- loadkernel
loady   - load binary file over serial line (ymodem mode) and update to flash
md      - memory display
mm      - memory modify (auto-incrementing address)
mmc     - MMC sub system
mmcinfo - display MMC info
mtest   - simple RAM read/write test
mw      - memory write (fill)
nand    - NAND sub-system
nm      - memory modify (constant address)
printenv- print environment variables
protect - enable or disable FLASH write protection
reset   - Perform RESET of the CPU
saveenv - save environment variables to persistent storage
setenv  - set environment variables
spi     - spi - Serial Flash sub-system
tftpboot- boot image via network using TFTP protocol
update  - update image, u-env, factory, u-logo, user, kernel, rootfs-r, rootfs-rw
usb     - USB sub-system
usbboot - boot from USB device
verify  - verify image, flash-info, hw-setting, flash-layout, u-boot, rescue, user, factory, kernel, rootfs-r, u-env
version - print monitor, compiler and linker version
ⓘ Example: ISmartAlarm® ISC5 SPOT IP-Camera - Memory Layout
mem=64M
mtdparts=snx-spi:
768k(uboot)
3M(kernel)
7M(rootfs)
4M(rescue)
1M(etc)
256K(userconfig)

loadkernel 0x00007FFC 0x0;
bootm 0x00008000

0x00000000,0x00000000 (u-logo)
0x00000000,0x00000FFF (hw-setting)
0x00001000,0x0005FFFF (u-boot)
0x00060000,0x0007EFFF (u-env)
0x0007F000,0x0007FFFF (flash-layout)
0x00080000,0x000BFFFF (factory)
0x000C0000,0x003BFFFF (kernel)
0x003C0000,0x00ABFFFF (rootfs-r)
0x00AC0000,0x00EBFFFF (rescue)
0x00EC0000,0x00FBFFFF (rootfs-rw)
0x00FC0000,0x00FFFFFF (user)

The example device uses an 64MB SOP8 SPI chip to store the firmware. Based on the mtdparts, the memory space is 0x00000000-0x00FFFFFF. this may be adapted to extract only a specific MTD partition. It is even possible to extract single files, like the shadow file, if the right memory address can be identified. It took 2 hours for extracting 64MB via UART. Additionnally, the device restarted automatically after 5min. This could be solved by monitoring the status and relaunching the memory dump from the last successfully received Byte. In any case, screenlog must be santized before continuing, by removing any additional text, which is not related to the actual memory dump. The actual command for extracting the whole memory is listed below. The .b output format is required for the next step.

=> md.b 0x0 0xFFFFFF
00000000: 0e 00 00 ea 80 6b d9 03 c4 6b d9 03 94 6b d9 03    .....k...k...k..
00000010: c8 6b d9 03 fc 5b d8 03 14 f0 9f e5 14 f0 9f e5    .k...[..........
00000020: 04 04 00 00 00 00 00 00 14 04 00 00 24 04 00 00    ............$...
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
00000040: 00 00 0f e1 1f 00 c0 e3 d3 00 80 e3 00 f0 2f e1    ............../.

[...]
Warning: Check that the log does not any additional non-printable characters

With this format, each line consits of 78 characters including the newline. This results in 78 Bytes transmitted, which effectivly represent only 16 Byte of Data, leading to an 80% overhead. It is obvious, that the the memory dump format is not usuable as is. The dump must be parse to get the original binary dump. For this [ https://github.com/gmbnomis/uboot-mdb-dump uboot-mdb-dump] script can be used.

python3 uboot_mdb_to_image.py < memory_dump.txt > memory_dump.bin

Related

Tested Devices

References