# ELF

The pwntools `ELF` class is the most useful class you will probably ever need, so understanding the full power of it *will* make your life easier. Essentially, the `ELF` class allows you to look up variables at runtime and stop hardcoding.

## Creating an ELF object

Creating an ELF object is very simple.

```python
elf = ELF('./vulnerable_program')
```

## Getting a process

Rather than specifying another process, we can just get it from the `ELF`:

```python
p = elf.process()
```

## The PLT and GOT

Want to do a `ret2plt`? Easy peasy.

```python
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
```

## Functions

Need to return to a function called `vuln`? Don't bother using a disassembler or debugger to find where it is.

```python
main_address = elf.functions['vuln']
```

Note that `elf.functions` returns a `Function` object, so if you only want the address you can use `elf.symbols`:

```python
main_address = elf.symbols['symbol']
```

## elf.libc

When local, we can grab the `libc` the binary is running with. Easy peasy.

```python
libc = elf.libc
```

## elf.search(needle, writable=False)

Search the entire binary for a specific sequence `needle` of characters. Very useful when trying to do a `ret2libc`. If `writable` is set it only checks for sections in memory that you can write to. Note this returns a **generator** so if you want the first match you have to enclose it in `next()`.

```python
binsh = next(libc.search(b'/bin/sh\x00'))
```

## elf.address

`elf.address` is the base address of the binary. If the binary does not have PIE enabled, then it's absolute; if it does, all addresses are relative (they pretend the binary base is `0x0`).

Setting the `address` value automatically updates the address of `symbols`, `got`, `plt` and `functions`, which makes it invaluable when adjusting for PIE or ASLR.

Let's say you leak the base address of `libc` while ASLR is enabled; with pwntools, it's ridiculously easy to get the location of `system` for a `ret2libc`.

```python
libc = elf.libc
libc.address = 0xf7f23000           # You 'leaked' this

system = libc.symbols['system']
binsh = next(libc.search(b'/bin/sh\x00'))
exit_addr = libc.symbols['exit']

# Now you can do the ret2libc
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ir0nstone.gitbook.io/notes/misc/pwntools/elf.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
