Beginning to decode ELF binaries cross-endian

This commit is contained in:
Pierre Pronchery 2011-06-04 01:43:10 +00:00
parent 34dfcf56ea
commit 430d35282a

View File

@ -76,12 +76,16 @@ static int _init_32(FormatPlugin * format);
static int _exit_32(FormatPlugin * format); static int _exit_32(FormatPlugin * format);
static int _section_32(FormatPlugin * format, char const * name); static int _section_32(FormatPlugin * format, char const * name);
static void _swap_32_ehdr(Elf32_Ehdr * ehdr); static void _swap_32_ehdr(Elf32_Ehdr * ehdr);
static void _swap_32_phdr(Elf32_Phdr * phdr);
static void _swap_32_shdr(Elf32_Shdr * shdr);
/* ELF64 */ /* ELF64 */
static int _init_64(FormatPlugin * format); static int _init_64(FormatPlugin * format);
static int _exit_64(FormatPlugin * format); static int _exit_64(FormatPlugin * format);
static int _section_64(FormatPlugin * format, char const * name); static int _section_64(FormatPlugin * format, char const * name);
static void _swap_64_ehdr(Elf64_Ehdr * ehdr); static void _swap_64_ehdr(Elf64_Ehdr * ehdr);
static void _swap_64_phdr(Elf64_Phdr * phdr);
static void _swap_64_shdr(Elf64_Shdr * shdr);
/* ElfStrtab */ /* ElfStrtab */
static int _elfstrtab_set(FormatPlugin * format, ElfStrtab * strtab, static int _elfstrtab_set(FormatPlugin * format, ElfStrtab * strtab,
@ -348,6 +352,8 @@ static int _elf_decode32(FormatPlugin * format)
|| helper->read(helper->format, &ehdr, sizeof(ehdr)) || helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr)) != sizeof(ehdr))
return -1; return -1;
if(ehdr.e_ident[EI_DATA] != elf_arch_native->endian)
_swap_32_ehdr(&ehdr);
if(_decode32_shdr(format, &ehdr, &shdr) != 0) if(_decode32_shdr(format, &ehdr, &shdr) != 0)
return -1; return -1;
if(_decode32_addr(format, &ehdr, &base) != 0 if(_decode32_addr(format, &ehdr, &base) != 0
@ -379,6 +385,7 @@ static int _decode32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
{ {
FormatPluginHelper * helper = format->helper; FormatPluginHelper * helper = format->helper;
ssize_t size; ssize_t size;
size_t i;
if(ehdr->e_shentsize == 0) if(ehdr->e_shentsize == 0)
{ {
@ -399,6 +406,9 @@ static int _decode32_shdr(FormatPlugin * format, Elf32_Ehdr * ehdr,
free(*shdr); free(*shdr);
return -1; return -1;
} }
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
for(i = 0; i < ehdr->e_shnum; i++)
_swap_32_shdr(*shdr + i);
return 0; return 0;
} }
@ -412,14 +422,18 @@ static int _decode32_addr(FormatPlugin * format, Elf32_Ehdr * ehdr,
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0) if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1; return -1;
for(i = 0; i < ehdr->e_phnum; i++) for(i = 0; i < ehdr->e_phnum; i++)
{
if(helper->read(helper->format, &phdr, sizeof(phdr)) if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr)) != sizeof(phdr))
return -1; return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X)) if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
_swap_32_phdr(&phdr);
if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{ {
*addr = phdr.p_vaddr; *addr = phdr.p_vaddr;
return 0; return 0;
} }
}
*addr = 0x0; *addr = 0x0;
return 0; return 0;
} }
@ -477,6 +491,8 @@ static int _elf_decode64(FormatPlugin * format)
|| helper->read(helper->format, &ehdr, sizeof(ehdr)) || helper->read(helper->format, &ehdr, sizeof(ehdr))
!= sizeof(ehdr)) != sizeof(ehdr))
return -1; return -1;
if(ehdr.e_ident[EI_DATA] != elf_arch_native->endian)
_swap_64_ehdr(&ehdr);
if(_decode64_shdr(format, &ehdr, &shdr) != 0) if(_decode64_shdr(format, &ehdr, &shdr) != 0)
return -1; return -1;
if(_decode64_addr(format, &ehdr, &base) != 0 if(_decode64_addr(format, &ehdr, &base) != 0
@ -508,6 +524,7 @@ static int _decode64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
{ {
FormatPluginHelper * helper = format->helper; FormatPluginHelper * helper = format->helper;
ssize_t size; ssize_t size;
size_t i;
if(ehdr->e_shentsize == 0) if(ehdr->e_shentsize == 0)
{ {
@ -528,6 +545,9 @@ static int _decode64_shdr(FormatPlugin * format, Elf64_Ehdr * ehdr,
free(*shdr); free(*shdr);
return -1; return -1;
} }
if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
for(i = 0; i < ehdr->e_shnum; i++)
_swap_64_shdr(*shdr + i);
return 0; return 0;
} }
@ -541,14 +561,18 @@ static int _decode64_addr(FormatPlugin * format, Elf64_Ehdr * ehdr,
if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0) if(helper->seek(helper->format, ehdr->e_phoff, SEEK_SET) < 0)
return -1; return -1;
for(i = 0; i < ehdr->e_phnum; i++) for(i = 0; i < ehdr->e_phnum; i++)
{
if(helper->read(helper->format, &phdr, sizeof(phdr)) if(helper->read(helper->format, &phdr, sizeof(phdr))
!= sizeof(phdr)) != sizeof(phdr))
return -1; return -1;
else if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X)) if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian)
_swap_64_phdr(&phdr);
if(phdr.p_type == PT_LOAD && phdr.p_flags & (PF_R | PF_X))
{ {
*addr = phdr.p_vaddr; *addr = phdr.p_vaddr;
return 0; return 0;
} }
}
*addr = 0x0; *addr = 0x0;
return 0; return 0;
} }
@ -791,6 +815,36 @@ static void _swap_32_ehdr(Elf32_Ehdr * ehdr)
} }
/* swap_32_phdr */
static void _swap_32_phdr(Elf32_Phdr * phdr)
{
phdr->p_type = _bswap32(phdr->p_type);
phdr->p_offset = _bswap32(phdr->p_offset);
phdr->p_vaddr = _bswap32(phdr->p_vaddr);
phdr->p_paddr = _bswap32(phdr->p_paddr);
phdr->p_filesz = _bswap32(phdr->p_filesz);
phdr->p_memsz = _bswap32(phdr->p_memsz);
phdr->p_flags = _bswap32(phdr->p_flags);
phdr->p_align = _bswap32(phdr->p_align);
}
/* swap_32_shdr */
static void _swap_32_shdr(Elf32_Shdr * shdr)
{
shdr->sh_name = _bswap32(shdr->sh_name);
shdr->sh_type = _bswap32(shdr->sh_type);
shdr->sh_flags = _bswap32(shdr->sh_flags);
shdr->sh_addr = _bswap32(shdr->sh_addr);
shdr->sh_offset = _bswap32(shdr->sh_offset);
shdr->sh_size = _bswap32(shdr->sh_size);
shdr->sh_link = _bswap32(shdr->sh_link);
shdr->sh_info = _bswap32(shdr->sh_info);
shdr->sh_addralign = _bswap32(shdr->sh_addralign);
shdr->sh_entsize = _bswap32(shdr->sh_entsize);
}
/* ELF64 */ /* ELF64 */
/* variables */ /* variables */
static Elf64_Shdr * es64 = NULL; static Elf64_Shdr * es64 = NULL;
@ -971,6 +1025,36 @@ static void _swap_64_ehdr(Elf64_Ehdr * ehdr)
} }
/* swap_64_phdr */
static void _swap_64_phdr(Elf64_Phdr * phdr)
{
phdr->p_type = _bswap32(phdr->p_type);
phdr->p_flags = _bswap32(phdr->p_flags);
phdr->p_offset = _bswap64(phdr->p_offset);
phdr->p_vaddr = _bswap64(phdr->p_vaddr);
phdr->p_paddr = _bswap64(phdr->p_paddr);
phdr->p_filesz = _bswap64(phdr->p_filesz);
phdr->p_memsz = _bswap64(phdr->p_memsz);
phdr->p_align = _bswap64(phdr->p_align);
}
/* swap_64_shdr */
static void _swap_64_shdr(Elf64_Shdr * shdr)
{
shdr->sh_name = _bswap32(shdr->sh_name);
shdr->sh_type = _bswap32(shdr->sh_type);
shdr->sh_flags = _bswap64(shdr->sh_flags);
shdr->sh_addr = _bswap64(shdr->sh_addr);
shdr->sh_offset = _bswap64(shdr->sh_offset);
shdr->sh_size = _bswap64(shdr->sh_size);
shdr->sh_link = _bswap32(shdr->sh_link);
shdr->sh_info = _bswap32(shdr->sh_info);
shdr->sh_addralign = _bswap64(shdr->sh_addralign);
shdr->sh_entsize = _bswap64(shdr->sh_entsize);
}
/* ElfStrtab */ /* ElfStrtab */
/* private */ /* private */
/* functions */ /* functions */