# Gadgets

Gadgets are small snippets of code followed by a `ret` instruction, e.g. `pop rdi; ret`. We can manipulate the `ret` of these gadgets in such a way as to string together a large chain of them to do what we want.

### Example

Let's for a minute pretend the stack looks like this during the execution of a `pop rdi; ret` gadget.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6rsFs6OPZXMxmI27r%2Fimage.png?alt=media\&token=0084cb45-876d-4165-9863-578d655eeedd)

What happens is fairly obvious - `0x10` gets popped into `rdi` as it is at the top of the stack during the `pop rdi`. Once the `pop` occurs, `rsp` moves:

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6rxCFqvlYzlurxKMW%2Fimage.png?alt=media\&token=1dcaf1b8-7ec4-4ad9-b776-105d41c1e003)

And since `ret` is equivalent to `pop rip`, `0x5655576724` gets moved into `rip`. Note how the stack is laid out for this.

### Utilising Gadgets

When we overwrite the return pointer, we overwrite the value pointed at by `rsp`. Once that value is popped, it points at the next value at the stack - but wait. We can overwrite the next value in the stack.

Let's say that we want to exploit a binary to jump to a `pop rdi; ret` gadget, pop `0x100` into `rdi` then jump to `flag()`. Let's step-by-step the execution.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6sIO-028Md3bAqC2q%2Fimage.png?alt=media\&token=467327d0-ae50-40e4-b38c-d0073e44e926)

On the *original* `ret`, which we overwrite the return pointer for, we pop the gadget address in. Now `rip` moves to point to the gadget, and `rsp` moves to the next memory address.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6siGn5gKQpFIburDO%2Fimage.png?alt=media\&token=0b6956b0-05d4-4e85-8f52-3def3ffe7125)

`rsp` moves to the `0x100`; `rip` to the `pop rdi`. Now when we pop, `0x100` gets moved into `rdi`.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6spSm54IYMXI_s_dQ%2Fimage.png?alt=media\&token=e785f7f4-2ee3-4c5e-8e23-741ea145be2b)

RSP moves onto the next items on the stack, the address of `flag()`. The `ret` is executed and `flag()` is called.

### Summary

Essentially, if the gadget pops values from the stack, simply place those values afterwards (including the `pop rip` in `ret`). If we want to pop `0x10` into `rdi` and then jump to `0x16`, our payload would look like this:

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6tEbSq0eMI851A8U4%2Fimage.png?alt=media\&token=d11bfbc0-92d0-437d-9304-7907d59dc4e0)

Note if you have multiple `pop` instructions, you can just add more values.

![](https://349224153-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MEwBGnjPgf263kl5vWP%2F-MM6rOOHiYqyLab3Pm1G%2F-MM6tVlFA6IkEX7iFCOH%2Fimage.png?alt=media\&token=ed91777f-7d86-4a80-a59b-738a2b4299c5)

{% hint style="info" %}
We use `rdi` as an example because, if you remember, that's the register for the first parameter in 64-bit. This means control of this register using this gadget is important.
{% endhint %}

### Finding Gadgets

We can use the tool [`ROPgadget`](https://github.com/JonathanSalwan/ROPgadget) to find possible gadgets.

```
$ ROPgadget --binary vuln-64

Gadgets information
============================================================
0x0000000000401069 : add ah, dh ; nop dword ptr [rax + rax] ; ret
0x000000000040109b : add bh, bh ; loopne 0x40110a ; nop ; ret
0x0000000000401037 : add byte ptr [rax], al ; add byte ptr [rax], al ; jmp 0x401024
[...]
```

Combine it with `grep` to look for specific registers.

```
$ ROPgadget --binary vuln-64 | grep rdi

0x0000000000401096 : or dword ptr [rdi + 0x404030], edi ; jmp rax
0x00000000004011db : pop rdi ; ret
```
