> 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/04.-ret2libc.md).

# 04. ret2libc

## 🔥 What is `libc` (from scratch)

`libc` = the standard C library on Linux.

It contains functions like:

* `printf`
* `system`
* `puts`
* `gets`
* `exit`

When your program runs, it doesn’t have its own implementations of these—it **links to libc** (shared library loaded in memory).

## 🧠 What is ret2libc

**ret2libc = Return-to-libc attack**

Instead of:

```
jumping to win()
```

you do:

```
jump to libc function → system("/bin/sh")
```

***

## ❓ Why do we need ret2libc?

Because in real binaries:

* ❌ No `win()` function
* ❌ NX (No Execute) → no shellcode
* ❌ Protections enabled

So you reuse existing code inside libc.

***

## 🎯 Goal of ret2libc

Execute:

```c
system("/bin/sh");
```

Which gives shell.

***

## ⚙️ What you need (3 things)

1. Address of `system`
2. Address of string `"/bin/sh"`
3. (optional) address of `exit`

***

## 🧠 Stack layout (important)

Payload looks like:

```
[ padding ]
[ system() address ]
[ return address (junk / exit) ]
[ address of "/bin/sh" ]
```

***

## 📦 Example flow (concept)

Let’s say:

```
system = 0x7ffff7e12345
/bin/sh = 0x7ffff7f67890
```

Payload:

```python
b"A"*offset + p64(system) + p64(0) + p64(binsh)
```

***

## ❗ Big problem (this is the real challenge)

👉 libc is loaded at **random address** (ASLR)

So:

```
system = UNKNOWN
/bin/sh = UNKNOWN
```

***

## 🔥 So how do we solve it?

We **leak an address first**.

***

## 🧪 Step-by-step ret2libc attack

### Step 1 — Leak libc address

Use a function like `puts`:

```
puts(puts@GOT)
```

This prints the real address of `puts` in memory.

***

### Step 2 — Calculate libc base

```
libc_base = leaked_puts - offset_of_puts_in_libc
```

***

### Step 3 — Calculate targets

```
system = libc_base + offset_system
binsh  = libc_base + offset_binsh
```

***

### Step 4 — Final payload

```
system("/bin/sh")
```

***

## 💡 Small conceptual example

Imagine:

```
puts leak = 0x7ffff7a5e5e0
puts offset = 0x80e50
```

Then:

```
libc_base = 0x7ffff7a5e5e0 - 0x80e50
```

Now:

```
system = libc_base + 0x4f550
/bin/sh = libc_base + 0x1b3e1a
```

***

## 🔁 Full attack flow

```
1. BOF → control RIP
2. Call puts(puts@GOT) → leak address
3. Return to main
4. Calculate libc base
5. Build second payload
6. Call system("/bin/sh")
```

***

## 🔧 Tools used

* GDB → debugging
* pwntools → scripting
* `checksec` → protections
* `ldd` → libc version

***

## 🧠 Key difference vs ret2win

| ret2win        | ret2libc        |
| -------------- | --------------- |
| jump to win()  | call system()   |
| address known  | address unknown |
| easy           | real-world      |
| no leak needed | leak required   |

***

## 🔥 Mental model (lock this in)

```
ret2win → use function inside binary
ret2libc → use function inside libc
```

***

## ⚠️ Common beginner mistakes

* Forgetting little endian
* Not leaking libc first
* Wrong libc version
* Missing return address alignment
* Not returning to main after leak

***

## 🚀 Where this leads next

After ret2libc:

* ROP chains
* one\_gadget
* PIE bypass
* full pwn challenges
