ELF Headers¶
The ELF header data structure is the same for both 32 and 64 bit architectures. For the 32 bit systems, Elf32 is used instead of "Elf64. One minor difference, some of the Elf64_ fields are actually a 32 bit value. There is much publicly available documentation on the ELF data structure, this is just an overview with notes about the Qualcomm implementation used for their binary blobs.
The ELF Header¶
The binary blobs used for firmware use an ELF header that defines the
type of executable. For Android this is either a executable file or a
shared library. The shared library blobs in the modem.img file appear
to be Android only, and unused by Android. Linux on the same hardware
works fine without them. The guess is these are to support the
Qualcomm testing program. The values of a file with an ELF header can
be displayed using the
readelf program from the GNU
Binutils.
| Type | Variable | Function |
|---|---|---|
| unsigned char | e_ident[EI_NIDENT] | ELF magic number |
| Elf64_Half | e_type | This the program type |
| Elf64_Half | e_machine | This is the architecture |
| Elf64_Word | e_version | The version of this data structure |
| Elf64_Addr | e_entry | Entry point virtual address |
| Elf64_Off | e_phoff | Program header table file offset |
| Elf64_Off | e_shoff | Section header table file offset |
| Elf64_Word | e_flags | |
| Elf64_Half | e_ehsize | The size of this data structure |
| Elf64_Half | e_phentsize | The size of the program header data structure |
| Elf64_Half | e_phnum | The number of program headers |
| Elf64_Half | e_shentsize | The size of the section header data structure |
| Elf64_Half | e_shnum | The number of sections headers |
| Elf64_Half | e_shstrndx | The string table |
The Program Header¶
The Program Headers data stricture are different between 32 and 64 bit architectures with p_flags being in a different location. This matters when you are parsing binary data. but otherwise the data structures are the same, with the same constants. The primary types we care about when reverse engineering PT_LOAD and PT_NULL.
PT_NULL doesn't get loaded at boot time, it's usually only the ELF header. On Linux, PT_NULL is also used as the container for the SSL certificates used to sign the blob. PT_LOAD is used for data that does get loaded into memory and is usually an executable.
The p_flags define how the data is used, it has three values, which
can be combined. These are executable data or read/write access.
| Type | Variable | Function |
|---|---|---|
| Elf32_Word | p_type | The type of program data |
| Elf32_Off | p_offset | The offset within the input file |
| Elf32_Addr | p_vaddr | The virtual address |
| Elf32_Addr | p_paddr | The pyhsical address |
| Elf32_Word | p_filesz | The size of the data in the input file |
| Elf32_Word | p_memsz | The size of the memory required |
| Elf32_Word | p_flags | The permission for this data |
| Elf32_Word | p_align | The alignment in memory, usually 4k |
| Type | Variable | Function |
|---|---|---|
| Elf64_Word | p_type | The type of program data |
| Elf64_Word | p_flags | The permission for this data |
| Elf64_Off | p_offset | Segment file offset |
| Elf64_Addr | p_paddr | Segment physical address |
| Elf64_Xword | p_filesz | Segment size in file |
| Elf64_Xword | p_memsz | Segment size in memory |
| Elf64_Xword | p_align | Segment alignment, file & memory |
Embedded SSL Certificates¶
On Android, the SSL certificates are stored in a file that contains only them. For Linux, these are buried in one of the program headers. This can be identified as it'll have a PT_NULL p_type, and a zero p_filesz. The SSL certificates can be found by scanning for the ASN.1 prefix. There are always three DER certificates used to sign a blob.
Section Header¶
Sections are stripped from all blobs on Android and Linux, so this
data structure isn't currently being used. This is here since it's
used in the ELF header.
| Type | Variable | Function |
|---|---|---|
| Elf32_Word | sh_name | |
| Elf32_Word | sh_type | |
| Elf32_Word | sh_flags | |
| Elf32_Addr | sh_addr | |
| Elf32_Off | sh_offset | |
| Elf32_Word | sh_size | |
| Elf32_Word | sh_link | |
| Elf32_Word | sh_info | |
| Elf32_Word | sh_addralign | |
| Elf32_Word | sh_entsize |