Introduction to x64
Last updated
Last updated
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
x64, γνωστό και ως x86-64, είναι μια αρχιτεκτονική επεξεργαστή 64-bit που χρησιμοποιείται κυρίως σε υπολογιστές και διακομιστές. Προέρχεται από την αρχιτεκτονική x86 που παράγεται από την Intel και αργότερα υιοθετήθηκε από την AMD με την ονομασία AMD64, είναι η κυρίαρχη αρχιτεκτονική στους προσωπικούς υπολογιστές και τους διακομιστές σήμερα.
x64 επεκτείνει την αρχιτεκτονική x86, διαθέτοντας 16 γενικούς καταχωρητές που φέρουν τις ετικέτες rax
, rbx
, rcx
, rdx
, rbp
, rsp
, rsi
, rdi
, και r8
έως r15
. Κάθε ένας από αυτούς μπορεί να αποθηκεύσει μια 64-bit (8-byte) τιμή. Αυτοί οι καταχωρητές διαθέτουν επίσης υποκαταχωρητές 32-bit, 16-bit και 8-bit για συμβατότητα και συγκεκριμένες εργασίες.
rax
- Παραδοσιακά χρησιμοποιείται για τιμές επιστροφής από συναρτήσεις.
rbx
- Συχνά χρησιμοποιείται ως βασικός καταχωρητής για λειτουργίες μνήμης.
rcx
- Συνήθως χρησιμοποιείται για μετρητές βρόχων.
rdx
- Χρησιμοποιείται σε διάφορους ρόλους, συμπεριλαμβανομένων των επεκτεινόμενων αριθμητικών λειτουργιών.
rbp
- Βασικός δείκτης για το πλαίσιο στοίβας.
rsp
- Δείκτης στοίβας, παρακολουθεί την κορυφή της στοίβας.
rsi
και rdi
- Χρησιμοποιούνται για δείκτες πηγής και προορισμού σε λειτουργίες συμβολοσειρών/μνήμης.
r8
έως r15
- Πρόσθετοι γενικοί καταχωρητές που εισήχθησαν στο x64.
Η σύμβαση κλήσης x64 διαφέρει μεταξύ των λειτουργικών συστημάτων. Για παράδειγμα:
Windows: Οι πρώτες τέσσερις παράμετροι μεταφέρονται στους καταχωρητές rcx
, rdx
, r8
, και r9
. Οι περαιτέρω παράμετροι τοποθετούνται στη στοίβα. Η τιμή επιστροφής είναι στον rax
.
System V (συνήθως χρησιμοποιούμενη σε συστήματα τύπου UNIX): Οι πρώτες έξι παραμέτρους ακέραιων ή δεικτών μεταφέρονται στους καταχωρητές rdi
, rsi
, rdx
, rcx
, r8
, και r9
. Η τιμή επιστροφής είναι επίσης στον rax
.
Εάν η συνάρτηση έχει περισσότερες από έξι εισόδους, οι υπόλοιπες θα μεταφερθούν στη στοίβα. RSP, ο δείκτης στοίβας, πρέπει να είναι ευθυγραμμισμένος 16 bytes, που σημαίνει ότι η διεύθυνση στην οποία δείχνει πρέπει να είναι διαιρετή του 16 πριν από οποιαδήποτε κλήση. Αυτό σημαίνει ότι κανονικά θα πρέπει να διασφαλίσουμε ότι το RSP είναι σωστά ευθυγραμμισμένο στον κώδικα μας πριν κάνουμε μια κλήση συνάρτησης. Ωστόσο, στην πράξη, οι κλήσεις συστήματος λειτουργούν πολλές φορές ακόμη και αν αυτή η απαίτηση δεν πληρούται.
Το Swift έχει τη δική του σύμβαση κλήσης που μπορεί να βρεθεί στο https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64
Οι εντολές x64 διαθέτουν ένα πλούσιο σύνολο, διατηρώντας τη συμβατότητα με τις προηγούμενες εντολές x86 και εισάγοντας νέες.
mov
: Μεταφορά μιας τιμής από έναν καταχωρητή ή θέση μνήμης σε άλλη.
Παράδειγμα: mov rax, rbx
— Μεταφέρει την τιμή από rbx
στο rax
.
push
και pop
: Πιέστε ή αφαιρέστε τιμές από/στην στοίβα.
Παράδειγμα: push rax
— Πιέζει την τιμή στο rax
στη στοίβα.
Παράδειγμα: pop rax
— Αφαιρεί την κορυφαία τιμή από τη στοίβα στο rax
.
add
και sub
: Λειτουργίες πρόσθεσης και αφαίρεσης.
Παράδειγμα: add rax, rcx
— Προσθέτει τις τιμές στο rax
και rcx
, αποθηκεύοντας το αποτέλεσμα στο rax
.
mul
και div
: Λειτουργίες πολλαπλασιασμού και διαίρεσης. Σημείωση: αυτές έχουν συγκεκριμένες συμπεριφορές σχετικά με τη χρήση των τελεστών.
call
και ret
: Χρησιμοποιούνται για κλήση και επιστροφή από συναρτήσεις.
int
: Χρησιμοποιείται για να προκαλέσει μια διακοπή λογισμικού. Π.χ., int 0x80
χρησιμοποιήθηκε για κλήσεις συστήματος σε 32-bit x86 Linux.
cmp
: Συγκρίνει δύο τιμές και ρυθμίζει τις σημαίες της CPU με βάση το αποτέλεσμα.
Παράδειγμα: cmp rax, rdx
— Συγκρίνει το rax
με το rdx
.
je
, jne
, jl
, jge
, ...: Συνθήκες άλματος που αλλάζουν τη ροή ελέγχου με βάση τα αποτελέσματα μιας προηγούμενης cmp
ή δοκιμής.
Παράδειγμα: Μετά από μια εντολή cmp rax, rdx
, je label
— Πηδάει στο label
αν το rax
είναι ίσο με το rdx
.
syscall
: Χρησιμοποιείται για κλήσεις συστήματος σε ορισμένα συστήματα x64 (όπως οι σύγχρονες Unix).
sysenter
: Μια βελτιστοποιημένη εντολή κλήσης συστήματος σε ορισμένες πλατφόρμες.
Πιέστε τον παλιό βασικό δείκτη: push rbp
(αποθηκεύει τον βασικό δείκτη του καλούντος)
Μεταφέρετε τον τρέχοντα δείκτη στοίβας στον βασικό δείκτη: mov rbp, rsp
(ρυθμίζει τον νέο βασικό δείκτη για την τρέχουσα συνάρτηση)
Δημιουργήστε χώρο στη στοίβα για τοπικές μεταβλητές: sub rsp, <size>
(όπου <size>
είναι ο αριθμός των bytes που χρειάζονται)
Μεταφέρετε τον τρέχοντα βασικό δείκτη στον δείκτη στοίβας: mov rsp, rbp
(απελευθερώνει τις τοπικές μεταβλητές)
Αφαιρέστε τον παλιό βασικό δείκτη από τη στοίβα: pop rbp
(αποκαθιστά τον βασικό δείκτη του καλούντος)
Επιστροφή: ret
(επιστρέφει τον έλεγχο στον καλούντα)
Υπάρχουν διαφορετικές κατηγορίες syscalls, μπορείτε να τις βρείτε εδώ:
Τότε, μπορείτε να βρείτε κάθε αριθμό syscall σε αυτή τη διεύθυνση:
Έτσι, για να καλέσετε το open
syscall (5) από την Unix/BSD class πρέπει να το προσθέσετε: 0x2000000
Έτσι, ο αριθμός syscall για να καλέσετε το open θα ήταν 0x2000005
Για να το μεταγλωττίσετε:
Για να εξαγάγετε τα bytes:
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)