pwnlib.elf — Working with ELF binaries

Exposes functionality for manipulating ELF files

pwnlib.elf.load(*args, **kwargs)[source]

Compatibility wrapper for pwntools v1

class pwnlib.elf.ELF(path)[source]

Encapsulates information about an ELF file.

Variables:
  • path – Path to the binary on disk
  • symbols – Dictionary of {name: address} for all symbols in the ELF
  • plt – Dictionary of {name: address} for all functions in the PLT
  • got – Dictionary of {name: address} for all function pointers in the GOT
  • libs – Dictionary of {path: address} for each shared object required to load the ELF

Example:

bash = ELF(which('bash'))
hex(bash.symbols['read'])
# 0x41dac0
hex(bash.plt['read'])
# 0x41dac0
u32(bash.read(bash.got['read'], 4))
# 0x41dac6
print disasm(bash.read(bash.plt['read'],16), arch='amd64')
# 0:   ff 25 1a 18 2d 00       jmp    QWORD PTR [rip+0x2d181a]        # 0x2d1820
# 6:   68 59 00 00 00          push   0x59
# b:   e9 50 fa ff ff          jmp    0xfffffffffffffa60
address[source]

Address of the lowest segment loaded in the ELF. When updated, cascades updates to segment vaddrs, section addrs, symbols, plt, and got.

>>> bash = ELF(which('bash'))
>>> old = bash.symbols['read']
>>> bash.address += 0x1000
>>> bash.symbols['read'] == old + 0x1000
True
asm(address, assembly)[source]

Assembles the specified instructions and inserts them into the ELF at the specified address.

The resulting binary can be saved with ELF.save()

bss(offset=0)[source]

Returns an index into the .bss segment

disasm(address, n_bytes)[source]

Returns a string of disassembled instructions at the specified virtual memory address

dwarf[source]

DWARF info for the elf

elfclass[source]

ELF class (32 or 64).

Note

Set during ELFFile._identify_file

elftype[source]

ELF type (EXEC, DYN, etc)

entry[source]

Entry point to the ELF

entrypoint[source]

Entry point to the ELF

executable_segments[source]

Returns: list of all segments which are executable.

get_data()[source]

Retrieve the raw data from the ELF file.

>>> bash = ELF(which('bash'))
>>> fd   = open(which('bash'))
>>> bash.get_data() == fd.read()
True
non_writable_segments[source]

Returns: list of all segments which are NOT writeable

offset_to_vaddr(offset)[source]

Translates the specified offset to a virtual address.

Parameters:offset (int) – Offset to translate
Returns:Virtual address which corresponds to the file offset, or None

Examples

>>> bash = ELF(which('bash'))
>>> bash.address == bash.offset_to_vaddr(0)
True
>>> bash.address += 0x123456
>>> bash.address == bash.offset_to_vaddr(0)
True
read(address, count)[source]

Read data from the specified virtual address

Parameters:
  • address (int) – Virtual address to read
  • count (int) – Number of bytes to read
Returns:

A string of bytes, or None

Examples

>>> bash = ELF(which('bash'))
>>> bash.read(bash.address+1, 3)
'ELF'
save(path)[source]

Save the ELF to a file

>>> bash = ELF(which('bash'))
>>> bash.save('/tmp/bash_copy')
>>> copy = file('/tmp/bash_copy')
>>> bash = file(which('bash'))
>>> bash.read() == copy.read()
True
search(needle, writable = False) → str generator[source]

Search the ELF’s virtual address space for the specified string.

Parameters:
  • needle (str) – String to search for.
  • writable (bool) – Search only writable sections.
Returns:

An iterator for each virtual address that matches.

Examples

>>> bash = ELF(which('bash'))
>>> bash.address + 1 == next(bash.search('ELF'))
True
>>> sh = ELF(which('bash'))
>>> # /bin/sh should only depend on libc
>>> libc_path = [key for key in sh.libs.keys() if 'libc' in key][0]
>>> libc = ELF(libc_path)
>>> # this string should be in there because of system(3)
>>> len(list(libc.search('/bin/sh'))) > 0
True
section(name)[source]

Gets data for the named section

Parameters:name (str) – Name of the section
Returns:String containing the bytes for that section
sections[source]

A list of all sections in the ELF

segments[source]

A list of all segments in the ELF

start[source]

Entry point to the ELF

vaddr_to_offset(address)[source]

Translates the specified virtual address to a file address

Parameters:address (int) – Virtual address to translate
Returns:Offset within the ELF file which corresponds to the address, or None.

Examples

>>> bash = ELF(which('bash'))
>>> 0 == bash.vaddr_to_offset(bash.address)
True
>>> bash.address += 0x123456
>>> 0 == bash.vaddr_to_offset(bash.address)
True
writable_segments[source]

Returns: list of all segments which are writeable

write(address, data)[source]

Writes data to the specified virtual address

Parameters:
  • address (int) – Virtual address to write
  • data (str) – Bytes to write

Note

This routine does not check the bounds on the write to ensure that it stays in the same segment.

Examples

>>> bash = ELF(which('bash'))
>>> bash.read(bash.address+1, 3)
'ELF'
>>> bash.write(bash.address, "HELO")
>>> bash.read(bash.address, 4)
'HELO'