pwnlib.elf
— Working with ELF binaries¶
-
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()
-
disasm
(address, n_bytes)[source]¶ Returns a string of disassembled instructions at the specified virtual memory address
-
static
from_assembly
(*a, **kw)[source]¶ Given an assembly listing, return a fully loaded ELF object which contains that assembly at its entry point.
Parameters: Example
>>> e = ELF.from_assembly('nop; foo: int 0x80', vma = 0x400000) >>> e.symbols['foo'] = 0x400001 >>> e.disasm(e.entry, 1) ' 400000: 90 nop' >>> e.disasm(e.symbols['foo'], 2) ' 400001: cd 80 int 0x80'
-
static
from_bytes
(*a, **kw)[source]¶ Given a sequence of bytes, return a fully loaded ELF object which contains those bytes at its entry point.
Parameters: Example
>>> e = ELF.from_bytes('\x90\xcd\x80', vma=0xc000) >>> print(e.disasm(e.entry, 3)) c000: 90 nop c001: cd 80 int 0x80
-
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
-
libc
[source]¶ If the ELF imports any libraries which contain ‘libc.so’, and we can determine the appropriate path to it on the local system, returns an ELF object pertaining to that libc.so.
Otherwise, returns
None
.
-
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: 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: 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
-
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
-
write
(address, data)[source]¶ Writes data to the specified virtual address
Parameters: - 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'
-
class
pwnlib.elf.
Core
(*a, **kw) → Core[source]¶ Enhances the inforation available about a corefile (which is an extension of the ELF format) by permitting extraction of information about the mapped data segments, and register state.
Registers can be accessed directly, e.g. via
core_obj.eax
.Mappings can be iterated in order via
core_obj.mappings
.