You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.0 KiB
155 lines
4.0 KiB
"""
|
|
Executable and Linkable Format (ELF), 32 bit, big or little endian
|
|
Used on *nix systems as a replacement of the older a.out format
|
|
|
|
Big-endian support kindly submitted by Craig McQueen (mcqueen-c#edsrd1!yzk!co!jp)
|
|
"""
|
|
from construct import *
|
|
import six
|
|
|
|
|
|
def elf32_body(ElfInt16, ElfInt32):
|
|
elf32_program_header = Struct("program_header",
|
|
Enum(ElfInt32("type"),
|
|
NULL = 0,
|
|
LOAD = 1,
|
|
DYNAMIC = 2,
|
|
INTERP = 3,
|
|
NOTE = 4,
|
|
SHLIB = 5,
|
|
PHDR = 6,
|
|
_default_ = Pass,
|
|
),
|
|
ElfInt32("offset"),
|
|
ElfInt32("vaddr"),
|
|
ElfInt32("paddr"),
|
|
ElfInt32("file_size"),
|
|
ElfInt32("mem_size"),
|
|
ElfInt32("flags"),
|
|
ElfInt32("align"),
|
|
)
|
|
|
|
elf32_section_header = Struct("section_header",
|
|
ElfInt32("name_offset"),
|
|
Pointer(lambda ctx: ctx._.strtab_data_offset + ctx.name_offset,
|
|
CString("name")
|
|
),
|
|
Enum(ElfInt32("type"),
|
|
NULL = 0,
|
|
PROGBITS = 1,
|
|
SYMTAB = 2,
|
|
STRTAB = 3,
|
|
RELA = 4,
|
|
HASH = 5,
|
|
DYNAMIC = 6,
|
|
NOTE = 7,
|
|
NOBITS = 8,
|
|
REL = 9,
|
|
SHLIB = 10,
|
|
DYNSYM = 11,
|
|
_default_ = Pass,
|
|
),
|
|
ElfInt32("flags"),
|
|
ElfInt32("addr"),
|
|
ElfInt32("offset"),
|
|
ElfInt32("size"),
|
|
ElfInt32("link"),
|
|
ElfInt32("info"),
|
|
ElfInt32("align"),
|
|
ElfInt32("entry_size"),
|
|
OnDemandPointer(lambda ctx: ctx.offset,
|
|
HexDumpAdapter(Field("data", lambda ctx: ctx.size))
|
|
),
|
|
)
|
|
|
|
return Struct("body",
|
|
Enum(ElfInt16("type"),
|
|
NONE = 0,
|
|
RELOCATABLE = 1,
|
|
EXECUTABLE = 2,
|
|
SHARED = 3,
|
|
CORE = 4,
|
|
),
|
|
Enum(ElfInt16("machine"),
|
|
NONE = 0,
|
|
M32 = 1,
|
|
SPARC = 2,
|
|
I386 = 3,
|
|
Motorolla68K = 4,
|
|
Motorolla88K = 5,
|
|
Intel860 = 7,
|
|
MIPS = 8,
|
|
_default_ = Pass
|
|
),
|
|
ElfInt32("version"),
|
|
ElfInt32("entry"),
|
|
ElfInt32("ph_offset"),
|
|
ElfInt32("sh_offset"),
|
|
ElfInt32("flags"),
|
|
ElfInt16("header_size"),
|
|
ElfInt16("ph_entry_size"),
|
|
ElfInt16("ph_count"),
|
|
ElfInt16("sh_entry_size"),
|
|
ElfInt16("sh_count"),
|
|
ElfInt16("strtab_section_index"),
|
|
|
|
# calculate the string table data offset (pointer arithmetics)
|
|
# ugh... anyway, we need it in order to read the section names, later on
|
|
Pointer(lambda ctx:
|
|
ctx.sh_offset + ctx.strtab_section_index * ctx.sh_entry_size + 16,
|
|
ElfInt32("strtab_data_offset"),
|
|
),
|
|
|
|
# program header table
|
|
Rename("program_table",
|
|
Pointer(lambda ctx: ctx.ph_offset,
|
|
Array(lambda ctx: ctx.ph_count,
|
|
elf32_program_header
|
|
)
|
|
)
|
|
),
|
|
|
|
# section table
|
|
Rename("sections",
|
|
Pointer(lambda ctx: ctx.sh_offset,
|
|
Array(lambda ctx: ctx.sh_count,
|
|
elf32_section_header
|
|
)
|
|
)
|
|
),
|
|
)
|
|
|
|
elf32_body_little_endian = elf32_body(ULInt16, ULInt32)
|
|
elf32_body_big_endian = elf32_body(UBInt16, UBInt32)
|
|
|
|
elf32_file = Struct("elf32_file",
|
|
Struct("identifier",
|
|
Magic(six.b("\x7fELF")),
|
|
Enum(Byte("file_class"),
|
|
NONE = 0,
|
|
CLASS32 = 1,
|
|
CLASS64 = 2,
|
|
),
|
|
Enum(Byte("encoding"),
|
|
NONE = 0,
|
|
LSB = 1,
|
|
MSB = 2,
|
|
),
|
|
Byte("version"),
|
|
Padding(9),
|
|
),
|
|
Embedded(IfThenElse("body", lambda ctx: ctx.identifier.encoding == "LSB",
|
|
elf32_body_little_endian,
|
|
elf32_body_big_endian,
|
|
)),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
obj = elf32_file.parse_stream(open("../../../tests/_ctypes_test.so", "rb"))
|
|
#[s.data.value for s in obj.sections]
|
|
print(obj)
|
|
|
|
|
|
|