I recently pulled a u-boot.bin
U-Boot image off of an embedded device. The file had no uImage header; it was just a raw binary file. Many times with loading a raw binary file into Ghidra, figuring out the base address is a challenge if it is not provided in a header or configuration file. That was exactly the case in this instance; all I had to go off of was the u-boot.bin
file. The base address was not listed or documented anywhere else.
The following is a little guide on how to figure out the Base Address to load U-Boot at in Ghidra in order to resolve symbols properly for ease of reverse engineering.
In this specific firmware file, the U-Boot Base Address is 0x49fb0000
. We are able to determine that by looking at the double word at offset 0x40
into the binary file.
00000000: ea00 0014 e59f f014 e59f f014 e59f f014 ................
00000010: e59f f014 e59f f014 e59f f014 e59f f014 ................
00000020: 49fb 01c0 49fb 0220 49fb 02a0 49fb 0320 I...I.. I...I..
00000030: 49fb 03a0 49fb 0420 49fb 04a0 1234 5678 I...I.. I....4Vx
00000040: 49fb 0000 49fb 0000 0000 0000 0000 0000 I...I...........
00000050: 0002 afac 0003 8594 e3a0 2c1f e3a0 30ff ..........,...0.
00000060: e582 3000 e10f 0000 e3c0 001f e380 00d3 ..0.............
This can be determined from looking at include/image.h
in the U-Boot Source:
/*
* Legacy format image header,
* all data in network byte order (aka natural aka bigendian).
*/
struct legacy_img_hdr {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
};
struct image_info {
ulong start, end; /* start/end of blob */
ulong image_start, image_len; /* start of image within blob, len of image */
ulong load; /* load addr for the image */
uint8_t comp, type, os; /* compression, type of image, os type */
uint8_t arch; /* CPU architecture */
};
Looking at the ghidra screen shot, we can see that image_len
is 0x2afac
(starting at offset 0x50), and thus by working backwards we can see that image_start
and end
are both the value 0 and that start
is 0x49fb0000
.
So by looking at either offset 0x44 or 0x40 we can reliably determine the u-boot load address.