ELF Backend

class cle.backends.ELF[source]

Bases: MetaELF

The main loader class for statically loading ELF executables. Uses the pyreadelf library where useful.

Useful backend options:

  • debug_symbols: Provides the path to a separate file which contains the binary’s debug symbols

  • discard_section_headers: Do not parse section headers. Use this if they are corrupted or malicious.

  • discard_program_headers: Do not parse program headers. Use this if the binary is for a platform whose ELF

    loader only looks at section headers, but whose toolchain generates program headers anyway.

is_default = True
__init__(*args, addend=None, debug_symbols=None, discard_section_headers=False, discard_program_headers=False, **kwargs)[source]
Parameters:
  • binary – The path to the binary to load

  • binary_stream – The open stream to this binary. The reference to this will be held until you call close.

  • is_main_bin – Whether this binary should be loaded as the main executable

close()[source]
classmethod check_compatibility(spec, obj)[source]

Performs a minimal static load of spec and returns whether it’s compatible with other_obj

classmethod check_magic_compatibility(stream)[source]

Check if a stream of bytes contains the same magic number as the main object

static is_compatible(stream)[source]

Determine quickly whether this backend can load an object from this stream

static extract_arch(reader)[source]
property initializers

Stub function. Should be overridden by backends that can provide initializer functions that ought to be run before execution reaches the entry point. Addresses should be rebased.

property finalizers

Stub function. Like initializers, but with finalizers.

property symbols_by_name
get_symbol(symid, symbol_table=None)[source]

Gets a Symbol object for the specified symbol.

Parameters:

symid – Either an index into .dynsym or the name of a symbol.

rebase(new_base)[source]

Rebase backend’s regions to the new base where they were mapped by the loader

class cle.backends.elf.ELFCore[source]

Bases: ELF

Loader class for ELF core files.

One key pain point when analyzing a core dump generated on a remote machine is that the paths to binaries are absolute (and may not exist or be the same on your local machine).

Therefore, you can use the options `remote_file_mapping to specify a dict mapping (easy if there are a small number of mappings) or remote_file_mapper to specify a function that accepts a remote file name and returns the local file name (useful if there are many mappings).

If you specify both remote_file_mapping and remote_file_mapper, remote_file_mapping is applied first, then the result is passed to remote_file_mapper.

Parameters:
  • executable – Optional path to the main binary of the core dump. If not supplied, ELFCore will attempt to figure it out automatically from the core dump.

  • remote_file_mapping – Optional dict that maps specific file names in the core dump to other file names.

  • remote_file_mapper – Optional function that is used to map every file name in the core dump to whatever is returned from this function.

is_default = True
__init__(*args, executable=None, remote_file_mapping=None, remote_file_mapper=None, **kwargs)[source]
Parameters:
  • binary – The path to the binary to load

  • binary_stream – The open stream to this binary. The reference to this will be held until you call close.

  • is_main_bin – Whether this binary should be loaded as the main executable

static is_compatible(stream)[source]

Determine quickly whether this backend can load an object from this stream

property threads

If this backend represents a dump of a running program, it may contain one or more thread contexts, i.e. register files. This property should contain a list of names for these threads, which should be unique.

thread_registers(thread=None)[source]

If this backend represents a dump of a running program, it may contain one or more thread contexts, i.e. register files. This method should return the register file for a given thread (as named in Backend.threads) as a dict mapping register names (as seen in archinfo) to numbers. If the thread is not specified, it should return the context for a “default” thread. If there are no threads, it should return an empty dict.

class cle.backends.elf.MetaELF[source]

Bases: Backend

A base class that implements functions used by all backends that can load an ELF.

__init__(*args, **kwargs)[source]
Parameters:
  • binary – The path to the binary to load

  • binary_stream – The open stream to this binary. The reference to this will be held until you call close.

  • is_main_bin – Whether this binary should be loaded as the main executable

supported_filetypes = ['elf']
property plt

Maps names to addresses.

property reverse_plt

Maps addresses to names.

property is_ppc64_abiv1

Returns whether the arch is PowerPC64 ABIv1.

Returns:

True if PowerPC64 ABIv1, False otherwise.

property is_ppc64_abiv2

Returns whether the arch is PowerPC64 ABIv2.

Returns:

True if PowerPC64 ABIv2, False otherwise.

property ppc64_initial_rtoc

Get initial rtoc value for PowerPC64 architecture.

static extract_soname(path)[source]

Extracts the shared object identifier from the path, or returns None if it cannot.

class cle.backends.elf.metaelf.Relro[source]

Bases: Enum

An enumeration.

NONE = 0
PARTIAL = 1
FULL = 2
class cle.backends.elf.symbol.ELFSymbol[source]

Bases: Symbol

Represents a symbol for the ELF format.

Variables:
  • binding (str) – The binding of this symbol as an ELF enum string

  • section – The section associated with this symbol, or None

  • _subtype – The ELFSymbolType of this symbol

__init__(owner, symb)[source]

Not documenting this since if you try calling it, you’re wrong.

property subtype: ELFSymbolType

A subclass’ ABI-specific types

class cle.backends.elf.symbol_type.ELFSymbolType[source]

Bases: SymbolSubType

ELF-specific symbol types

STT_NOTYPE = (0, None)
STT_OBJECT = (1, None)
STT_FUNC = (2, None)
STT_SECTION = (3, None)
STT_FILE = (4, None)
STT_COMMON = (5, None)
STT_TLS = (6, None)
STT_LOOS = (10, None)
STT_HIOS = (12, None)
STT_LOPROC = (13, None)
STT_HIPROC = (15, None)
STT_GNU_IFUNC = (10, 'gnu')
__init__(*args)[source]
property elf_value
property os_proc
property is_custom_os_proc
to_base_type()[source]

A subclass’ ABI-specific mapping to :SymbolType:

__new__(value)

This is just a nice way to allow for just specifying the int for default types: ELFSymbolType(10) rather than ELFSymbolType((10,None)).

Idea courtesy: https://stackoverflow.com/q/24105268/1137728.

We don’t need to implement the str parsing like the SO link above since Enum already has built-in item access: ELFSymbolType[‘STT_FUNC’].

class cle.backends.elf.regions.ELFSegment[source]

Bases: Segment

Represents a segment for the ELF format.

__init__(readelf_seg, relro=False)[source]
property is_readable
property is_writable
property is_executable
property is_relro
class cle.backends.elf.regions.ELFSection[source]

Bases: Section

SHF_WRITE = 1
SHF_ALLOC = 2
SHF_EXECINSTR = 4
SHF_STRINGS = 32
SHT_NULL = 'SHT_NULL'
__init__(readelf_sec, remap_offset=0)[source]
Parameters:
  • name (str) – The name of the section

  • offset (int) – The offset into the binary file this section begins

  • vaddr (int) – The address in virtual memory this section begins

  • size (int) – How large this section is

property is_readable

Whether this section has read permissions

property is_active
property is_writable

Whether this section has write permissions

property occupies_memory
property is_executable

Whether this section has execute permissions

property is_strings
property only_contains_uninitialized_data

Whether this section is initialized to zero after the executable is loaded.

class cle.backends.elf.variable.Variable[source]

Bases: object

Variable for DWARF from a DW_TAG_variable or DW_TAG_formal_parameter

Variables:
  • name (str) – The name of the variable

  • relative_addr – The relative addr (base addr depends on the type)

  • lexical_block – For a local variable, the lexical block where the variable is declared

__init__(elf_object: ELF)[source]
Parameters:

elf_object (ELF)

static from_die(die: DIE, expr_parser, elf_object: ELF, lexical_block: LexicalBlock | None = None)[source]
Parameters:
rebased_addr_from_cfa(cfa: int)[source]

The address of this variable in the global memory.

Parameters:

cfa (int) – The canonical frame address as described by the DWARF standard.

property rebased_addr
property addr

Please use ‘relative_addr’ or ‘rebased_addr’ instead.

property type: VariableType
property sort: str
class cle.backends.elf.variable.MemoryVariable[source]

Bases: Variable

This includes all variables that are not on the stack and not in a register. So all global variables, and also local static variables in C!

__init__(elf_object: ELF, relative_addr)[source]
Parameters:

elf_object (ELF)

property rebased_addr
property sort: str
class cle.backends.elf.variable.StackVariable[source]

Bases: Variable

Stack Variable from DWARF.

__init__(elf_object: ELF, relative_addr)[source]
Parameters:

elf_object (ELF)

rebased_addr_from_cfa(cfa: int)[source]

The address of this variable in the global memory.

Parameters:

cfa (int) – The canonical frame address as described by the DWARF standard.

property sort: str
class cle.backends.elf.variable.RegisterVariable[source]

Bases: Variable

Register Variable from DWARF.

__init__(elf_object: ELF, register_addr)[source]
Parameters:

elf_object (ELF)

property sort: str
class cle.backends.elf.variable_type.VariableType[source]

Bases: object

Entry class for DW_TAG_xxx_type

Parameters:
  • name (str) – name of the type

  • byte_size (int) – amount of bytes the type take in memory

  • elf_object – elf object to reference to (useful for pointer,…)

Variables:
  • name – name of the type

  • byte_size – amount of bytes the type take in memory

__init__(name: str, byte_size: int, elf_object)[source]
Parameters:
static read_from_die(die: DIE, elf_object)[source]

entry method to read a DW_TAG_xxx_type

Parameters:

die (DIE)

static supported_die(die: DIE) bool[source]
Return type:

bool

Parameters:

die (DIE)

class cle.backends.elf.variable_type.PointerType[source]

Bases: VariableType

Entry class for DW_TAG_pointer_type. It is inherited from VariableType

Parameters:
  • byte_size (int) – amount of bytes the type take in memory

  • elf_object – elf object to reference to (useful for pointer,…)

  • referenced_offset (int) – type of the referenced as offset in the compilation_unit

__init__(byte_size: int, elf_object, referenced_offset: int)[source]
Parameters:
  • byte_size (int)

  • referenced_offset (int)

classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_pointer_type. return None when there is no byte_size or type attribute.

Parameters:

die (DIE)

property referenced_type

attribute to get the referenced type. Return None if the type is not loaded

class cle.backends.elf.variable_type.BaseType[source]

Bases: VariableType

Entry class for DW_TAG_base_type. It is inherited from VariableType

classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_base_type. return None when there is no byte_size attribute.

Parameters:

die (DIE)

class cle.backends.elf.variable_type.StructType[source]

Bases: VariableType

Entry class for DW_TAG_structure_type. It is inherited from VariableType

Parameters:
  • name (str) – name of the type

  • byte_size (int) – amount of bytes the type take in memory

  • elf_object – elf object to reference to (useful for pointer,…)

__init__(name: str, byte_size: int, elf_object, members)[source]
Parameters:
classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_structure_type. return None when there is no byte_size attribute.

Parameters:

die (DIE)

class cle.backends.elf.variable_type.UnionType[source]

Bases: StructType

Entry class for DW_TAG_union_type. Inherits from StructType to make it trivial.

class cle.backends.elf.variable_type.StructMember[source]

Bases: object

Entry class for DW_TAG_member. This is not a type but a named member inside a struct. Use the property type to get its variable type.

Parameters:
  • name (str) – name of the member

  • addr_offset (int) – address offset of the member in the struct

  • elf_object – elf object to reference to (useful for pointer,…)

  • type_offset – type as offset in the compilation_unit

Variables:

name – name of the member

__init__(name: str, addr_offset: int, type_offset, elf_object)[source]
Parameters:
  • name (str)

  • addr_offset (int)

classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_member_type. return None when there is no type attribute.

Parameters:

die (DIE)

property type

attribute to get the type of the member. Return None if the type is not loaded

class cle.backends.elf.variable_type.ArrayType[source]

Bases: VariableType

Entry class for DW_TAG_array_type. It is inherited from VariableType

Parameters:
  • byte_size – amount of bytes the type take in memory

  • elf_object – elf object to reference to (useful for pointer,…)

  • element_offset – type of the array elements as offset in the compilation_unit

__init__(byte_size, elf_object, element_offset)[source]
classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_array_type. return None when there is no type attribute.

Parameters:

die (DIE)

property element_type
class cle.backends.elf.variable_type.TypedefType[source]

Bases: VariableType

Entry class for DW_TAG_typedef. Inherits from VariableType.

Parameters:
  • name (str) – name of the new type

  • elf_object – elf object to reference to (useful for pointer,…)

  • type_offset – type as offset in the compilation_unit

__init__(name: str, byte_size, elf_object, type_offset)[source]
Parameters:

name (str)

classmethod read_from_die(die: DIE, elf_object)[source]

read an entry of DW_TAG_member_type. return None when there is no type attribute.

Parameters:

die (DIE)

property type

attribute to get the type of the member. Return None if the type is not loaded

References

class cle.backends.elf.lsda.ExceptionTableHeader[source]

Bases: object

__init__(lp_start, ttype_encoding, ttype_offset, call_site_encoding, call_site_table_len)[source]
lp_start
ttype_encoding
ttype_offset
call_site_encoding
call_site_table_len
class cle.backends.elf.lsda.CallSiteEntry[source]

Bases: object

__init__(cs_start, cs_len, cs_lp, cs_action)[source]
cs_start
cs_len
cs_lp
cs_action
class cle.backends.elf.lsda.LSDAExceptionTable[source]

Bases: object

LSDA exception table parser.

TODO: Much of this class should be eventually moved to pyelftools.

__init__(stream, bits, little_endian=True)[source]
parse_lsda(address, offset)[source]
class cle.backends.elf.hashtable.ELFHashTable[source]

Bases: object

Functions to do lookup from a HASH section of an ELF file.

Information: http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-48031.html

__init__(symtab, stream, offset, arch)[source]
Parameters:
  • symtab – The symbol table to perform lookups from (as a pyelftools SymbolTableSection).

  • stream – A file-like object to read from the ELF’s memory.

  • offset – The offset in the object where the table starts.

  • arch – The ArchInfo object for the ELF file.

get(k)[source]

Perform a lookup. Returns a pyelftools Symbol object, or None if there is no match.

Parameters:

k – The string to look up.

static elf_hash(key)[source]
class cle.backends.elf.hashtable.GNUHashTable[source]

Bases: object

Functions to do lookup from a GNU_HASH section of an ELF file.

Information: https://blogs.oracle.com/ali/entry/gnu_hash_elf_sections

__init__(symtab, stream, offset, arch)[source]
Parameters:
  • symtab – The symbol table to perform lookups from (as a pyelftools SymbolTableSection).

  • stream – A file-like object to read from the ELF’s memory.

  • offset – The offset in the object where the table starts.

  • arch – The ArchInfo object for the ELF file.

get(k)[source]

Perform a lookup. Returns a pyelftools Symbol object, or None if there is no match.

Parameters:

k – The string to look up

static gnu_hash(key)[source]
class cle.backends.elf.subprogram.LexicalBlock[source]

Bases: object

A lexical block is a sequence of source statements, e.g. a while/for loop or an if statement or some bracketed block.

Corresponds to a DW_TAG_LexicalBlock in DWARF.

Parameters:
  • super_block – The lexical block which contains this block

  • low_pc – The relative start address of the block

  • high_pc – The relative end address of the block

Variables:
  • low_pc – The relative start address of the subprogram

  • high_pc – The relative end address of the subprogram

  • child_blocks – Lexical blocks inside this block (only direct childs)

__init__(low_pc, high_pc) None[source]
Return type:

None

class cle.backends.elf.subprogram.Subprogram[source]

Bases: LexicalBlock

DW_TAG_subprogram for DWARF. The behavior is mostly inherited from LexicalBlock to avoid redundancy.

Parameters:
  • name (str) – The name of the function/program

  • low_pc – The relative start address of the subprogram

  • high_pc – The relative end address of the subprogram

Variables:
  • name – The name of the function/program

  • local_variables – All local variables in a Subprogram (they may reside in serveral child blocks)

__init__(name, low_pc, high_pc) None[source]
Return type:

None

class cle.backends.elf.compilation_unit.CompilationUnit[source]

Bases: object

CompilationUnit for DWARF See http://dwarfstd.org/doc/DWARF5.pdf page 60

__init__(name, comp_dir, low_pc, high_pc, language, elf_object)[source]
property min_addr
property max_addr