Firmware Acquisition: U-Boot
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.
- 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
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
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
=> help md md - memory display Usage: md [.b, .w, .l] address [# of objects]
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 ............../. [...]
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
- ISmartAlarm® ISC5 SPOT IP-Camera
- ... more ...
- http://www.denx.de/wiki/DULG/Manual (Accessed: 20. October 2020)
- http://www.denx.de/wiki/view/DULG/UBootCmdGroupMemory#Section_UBootCmdMd (Accessed: 20. October 2020)
- https://www.digi.com/resources/documentation/digidocs/PDFs/90000852.pdf (Accessed: 20. October 2020)