macOS IPC - Inter Process Communication
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Το Mach χρησιμοποιεί tasks ως τη μικρότερη μονάδα για την κοινή χρήση πόρων, και κάθε task μπορεί να περιέχει πολλές νήματα. Αυτές οι tasks και νήματα αντιστοιχούν 1:1 σε διαδικασίες και νήματα POSIX.
Η επικοινωνία μεταξύ των tasks συμβαίνει μέσω της Mach Inter-Process Communication (IPC), χρησιμοποιώντας κανάλια επικοινωνίας ενός μόνο τρόπου. Μηνύματα μεταφέρονται μεταξύ θυρών, οι οποίες λειτουργούν ως ουρές μηνυμάτων που διαχειρίζεται ο πυρήνας.
Μια θύρα είναι το βασικό στοιχείο της Mach IPC. Μπορεί να χρησιμοποιηθεί για να στείλει μηνύματα και να τα λάβει.
Κάθε διαδικασία έχει έναν πίνακα IPC, όπου είναι δυνατή η εύρεση των mach ports της διαδικασίας. Το όνομα μιας mach port είναι στην πραγματικότητα ένας αριθμός (ένας δείκτης στο αντικείμενο του πυρήνα).
Μια διαδικασία μπορεί επίσης να στείλει ένα όνομα θύρας με ορισμένα δικαιώματα σε μια διαφορετική task και ο πυρήνας θα κάνει αυτή την καταχώρηση στον πίνακα IPC της άλλης task να εμφανιστεί.
Τα δικαιώματα θύρας, τα οποία καθορίζουν ποιες λειτουργίες μπορεί να εκτελέσει μια task, είναι κλειδί για αυτή την επικοινωνία. Τα πιθανά δικαιώματα θύρας είναι (ορισμοί από εδώ):
Δικαίωμα λήψης, το οποίο επιτρέπει τη λήψη μηνυμάτων που αποστέλλονται στη θύρα. Οι Mach ports είναι MPSC (πολλοί παραγωγοί, ένας καταναλωτής) ουρές, που σημαίνει ότι μπορεί να υπάρχει μόνο ένα δικαίωμα λήψης για κάθε θύρα σε ολόκληρο το σύστημα (σε αντίθεση με τους σωλήνες, όπου πολλές διαδικασίες μπορούν να κατέχουν περιγραφές αρχείων στο αναγνωστικό άκρο ενός σωλήνα).
Μια task με το Δικαίωμα Λήψης μπορεί να λαμβάνει μηνύματα και να δημιουργεί Δικαιώματα Αποστολής, επιτρέποντάς της να στέλνει μηνύματα. Αρχικά μόνο η δική της task έχει Δικαίωμα Λήψης πάνω στη θύρα της.
Εάν ο ιδιοκτήτης του Δικαιώματος Λήψης πεθάνει ή το σκοτώσει, το δικαίωμα αποστολής γίνεται άχρηστο (νεκρό όνομα).
Δικαίωμα αποστολής, το οποίο επιτρέπει την αποστολή μηνυμάτων στη θύρα.
Το Δικαίωμα Αποστολής μπορεί να κλωνοποιηθεί έτσι ώστε μια task που κατέχει ένα Δικαίωμα Αποστολής να μπορεί να κλωνοποιήσει το δικαίωμα και να το παραχωρήσει σε μια τρίτη task.
Σημειώστε ότι τα δικαιώματα θύρας μπορούν επίσης να περαστούν μέσω μηνυμάτων Mac.
Δικαίωμα αποστολής-μία φορά, το οποίο επιτρέπει την αποστολή ενός μηνύματος στη θύρα και στη συνέχεια εξαφανίζεται.
Αυτό το δικαίωμα δεν μπορεί να κλωνοποιηθεί, αλλά μπορεί να μετακινηθεί.
Δικαίωμα συνόλου θυρών, το οποίο δηλώνει ένα σύνολο θυρών αντί για μια μόνο θύρα. Η αποδέσμευση ενός μηνύματος από ένα σύνολο θυρών αποδεσμεύει ένα μήνυμα από μία από τις θύρες που περιέχει. Τα σύνολα θυρών μπορούν να χρησιμοποιηθούν για να ακούσουν σε πολλές θύρες ταυτόχρονα, πολύ όπως το select
/poll
/epoll
/kqueue
στο Unix.
Νεκρό όνομα, το οποίο δεν είναι πραγματικά δικαίωμα θύρας, αλλά απλώς μια θέση κράτησης. Όταν μια θύρα καταστραφεί, όλα τα υπάρχοντα δικαιώματα θύρας στη θύρα μετατρέπονται σε νεκρά ονόματα.
Οι tasks μπορούν να μεταφέρουν ΔΙΚΑΙΩΜΑΤΑ ΑΠΟΣΤΟΛΗΣ σε άλλους, επιτρέποντάς τους να στέλνουν μηνύματα πίσω. Τα ΔΙΚΑΙΩΜΑΤΑ ΑΠΟΣΤΟΛΗΣ μπορούν επίσης να κλωνοποιηθούν, έτσι ώστε μια task να μπορεί να διπλασιάσει και να δώσει το δικαίωμα σε μια τρίτη task. Αυτό, σε συνδυασμό με μια ενδιάμεση διαδικασία γνωστή ως bootstrap server, επιτρέπει την αποτελεσματική επικοινωνία μεταξύ των tasks.
Οι θύρες αρχείων επιτρέπουν την ενσωμάτωση περιγραφών αρχείων σε θύρες Mac (χρησιμοποιώντας δικαιώματα θύρας Mach). Είναι δυνατή η δημιουργία ενός fileport
από μια δεδομένη FD χρησιμοποιώντας το fileport_makeport
και η δημιουργία μιας FD από μια fileport χρησιμοποιώντας το fileport_makefd
.
Όπως αναφέρθηκε προηγουμένως, είναι δυνατή η αποστολή δικαιωμάτων χρησιμοποιώντας μηνύματα Mach, ωστόσο, δεν μπορείτε να στείλετε ένα δικαίωμα χωρίς να έχετε ήδη ένα δικαίωμα για να στείλετε ένα μήνυμα Mach. Έτσι, πώς καθορίζεται η πρώτη επικοινωνία;
Για αυτό, εμπλέκεται ο bootstrap server (launchd στο mac), καθώς ο καθένας μπορεί να αποκτήσει ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στον bootstrap server, είναι δυνατή η αίτηση για ένα δικαίωμα να στείλει ένα μήνυμα σε μια άλλη διαδικασία:
Η Task A δημιουργεί μια νέα θύρα, αποκτώντας το ΔΙΚΑΙΩΜΑ ΛΗΨΗΣ πάνω της.
Η Task A, ως κάτοχος του Δικαιώματος Λήψης, δημιουργεί ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ για τη θύρα.
Η Task A καθορίζει μια σύνδεση με τον bootstrap server, και του στέλνει το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ για τη θύρα που δημιούργησε στην αρχή.
Θυμηθείτε ότι ο καθένας μπορεί να αποκτήσει ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στον bootstrap server.
Η Task A στέλνει ένα μήνυμα bootstrap_register
στον bootstrap server για να συσχετίσει τη δεδομένη θύρα με ένα όνομα όπως com.apple.taska
Η Task B αλληλεπιδρά με τον bootstrap server για να εκτελέσει μια bootstrap αναζήτηση για το όνομα υπηρεσίας (bootstrap_lookup
). Έτσι, για να μπορέσει να απαντήσει ο bootstrap server, η task B θα του στείλει ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ σε μια θύρα που δημιούργησε προηγουμένως μέσα στο μήνυμα αναζήτησης. Εάν η αναζήτηση είναι επιτυχής, ο server διπλασιάζει το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ που έλαβε από την Task A και το μεταδίδει στην Task B.
Θυμηθείτε ότι ο καθένας μπορεί να αποκτήσει ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στον bootstrap server.
Με αυτό το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ, η Task B είναι ικανή να στείλει ένα μήνυμα στην Task A.
Για μια αμφίδρομη επικοινωνία, συνήθως η task B δημιουργεί μια νέα θύρα με ένα ΔΙΚΑΙΩΜΑ ΛΗΨΗΣ και ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ, και δίνει το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στην Task A ώστε να μπορεί να στέλνει μηνύματα στην TASK B (αμφίδρομη επικοινωνία).
Ο bootstrap server δεν μπορεί να πιστοποιήσει το όνομα υπηρεσίας που δηλώνει μια task. Αυτό σημαίνει ότι μια task θα μπορούσε δυνητικά να παριστάνει οποιαδήποτε συστημική task, όπως να δηλώνει ψευδώς ένα όνομα υπηρεσίας εξουσιοδότησης και στη συνέχεια να εγκρίνει κάθε αίτημα.
Στη συνέχεια, η Apple αποθηκεύει τα ονόματα υπηρεσιών που παρέχονται από το σύστημα σε ασφαλή αρχεία ρυθμίσεων, που βρίσκονται σε καταλόγους προστατευμένους από SIP: /System/Library/LaunchDaemons
και /System/Library/LaunchAgents
. Μαζί με κάθε όνομα υπηρεσίας, το σχετικό δυαδικό αρχείο αποθηκεύεται επίσης. Ο bootstrap server θα δημιουργήσει και θα διατηρήσει ένα ΔΙΚΑΙΩΜΑ ΛΗΨΗΣ για καθένα από αυτά τα ονόματα υπηρεσίας.
Για αυτές τις προκαθορισμένες υπηρεσίες, η διαδικασία αναζήτησης διαφέρει ελαφρώς. Όταν αναζητείται ένα όνομα υπηρεσίας, το launchd ξεκινά την υπηρεσία δυναμικά. Η νέα ροή εργασίας είναι ως εξής:
Η Task B ξεκινά μια bootstrap αναζήτηση για ένα όνομα υπηρεσίας.
Ο launchd ελέγχει αν η task εκτελείται και αν δεν εκτελείται, την ξεκινά.
Η Task A (η υπηρεσία) εκτελεί έναν bootstrap check-in (bootstrap_check_in()
). Εδώ, ο bootstrap server δημιουργεί ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ, το διατηρεί και μεταφέρει το ΔΙΚΑΙΩΜΑ ΛΗΨΗΣ στην Task A.
Ο launchd διπλασιάζει το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ και το στέλνει στην Task B.
Η Task B δημιουργεί μια νέα θύρα με ένα ΔΙΚΑΙΩΜΑ ΛΗΨΗΣ και ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ, και δίνει το ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στην Task A (την υπηρεσία) ώστε να μπορεί να στέλνει μηνύματα στην TASK B (αμφίδρομη επικοινωνία).
Ωστόσο, αυτή η διαδικασία ισχύει μόνο για προκαθορισμένες συστημικές tasks. Οι μη συστημικές tasks λειτουργούν ακόμα όπως περιγράφηκε αρχικά, γεγονός που θα μπορούσε δυνητικά να επιτρέψει την παριστάνωση.
Επομένως, ο launchd δεν πρέπει ποτέ να καταρρεύσει ή ολόκληρο το σύστημα θα καταρρεύσει.
Η συνάρτηση mach_msg
, που είναι ουσιαστικά μια κλήση συστήματος, χρησιμοποιείται για την αποστολή και λήψη μηνυμάτων Mach. Η συνάρτηση απαιτεί το μήνυμα που θα σταλεί ως αρχικό επιχείρημα. Αυτό το μήνυμα πρέπει να ξεκινά με μια δομή mach_msg_header_t
, ακολουθούμενη από το πραγματικό περιεχόμενο του μηνύματος. Η δομή ορίζεται ως εξής:
Διεργασίες που κατέχουν ένα receive right μπορούν να λαμβάνουν μηνύματα σε μια Mach θύρα. Αντίθετα, οι senders έχουν παραχωρηθεί ένα send ή ένα send-once right. Το send-once right προορίζεται αποκλειστικά για την αποστολή ενός μόνο μηνύματος, μετά το οποίο καθίσταται άκυρο.
Το αρχικό πεδίο msgh_bits
είναι μια bitmap:
Το πρώτο bit (το πιο σημαντικό) χρησιμοποιείται για να υποδείξει ότι ένα μήνυμα είναι σύνθετο (περισσότερα για αυτό παρακάτω)
Τα 3ο και 4ο χρησιμοποιούνται από τον πυρήνα
Τα 5 λιγότερο σημαντικά bits του 2ου byte μπορούν να χρησιμοποιηθούν για voucher: ένας άλλος τύπος θύρας για την αποστολή συνδυασμών κλειδιού/τιμής.
Τα 5 λιγότερο σημαντικά bits του 3ου byte μπορούν να χρησιμοποιηθούν για local port
Τα 5 λιγότερο σημαντικά bits του 4ου byte μπορούν να χρησιμοποιηθούν για remote port
Οι τύποι που μπορούν να καθοριστούν στο voucher, local και remote ports είναι (από mach/message.h):
Για παράδειγμα, MACH_MSG_TYPE_MAKE_SEND_ONCE
μπορεί να χρησιμοποιηθεί για να υποδείξει ότι ένα δικαίωμα αποστολής μία φορά θα πρέπει να παραχθεί και να μεταφερθεί για αυτή την θύρα. Μπορεί επίσης να καθοριστεί MACH_PORT_NULL
για να αποτραπεί ο παραλήπτης να μπορεί να απαντήσει.
Για να επιτευχθεί μια εύκολη διπλής κατεύθυνσης επικοινωνία, μια διαδικασία μπορεί να καθορίσει μια mach port στην κεφαλίδα μήνυματος που ονομάζεται θύρα απάντησης (msgh_local_port
) όπου ο παραλήπτης του μηνύματος μπορεί να στείλει μια απάντηση σε αυτό το μήνυμα.
Σημειώστε ότι αυτός ο τύπος διπλής κατεύθυνσης επικοινωνίας χρησιμοποιείται σε μηνύματα XPC που αναμένουν μια απάντηση (xpc_connection_send_message_with_reply
και xpc_connection_send_message_with_reply_sync
). Αλλά συνήθως δημιουργούνται διαφορετικές θύρες όπως εξηγήθηκε προηγουμένως για να δημιουργηθεί η διπλής κατεύθυνσης επικοινωνία.
Τα άλλα πεδία της κεφαλίδας μηνύματος είναι:
msgh_size
: το μέγεθος ολόκληρου του πακέτου.
msgh_remote_port
: η θύρα στην οποία αποστέλλεται αυτό το μήνυμα.
msgh_voucher_port
: mach vouchers.
msgh_id
: το ID αυτού του μηνύματος, το οποίο ερμηνεύεται από τον παραλήπτη.
Σημειώστε ότι τα mach μηνύματα αποστέλλονται μέσω μιας mach port
, η οποία είναι ένα κανάλι επικοινωνίας με έναν μόνο παραλήπτη, πολλούς αποστολείς που είναι ενσωματωμένο στον πυρήνα mach. Πολλές διαδικασίες μπορούν να στείλουν μηνύματα σε μια mach port, αλλά σε οποιαδήποτε στιγμή μόνο μία διαδικασία μπορεί να διαβάσει από αυτήν.
Τα μηνύματα σχηματίζονται από την κεφαλίδα mach_msg_header_t
που ακολουθείται από το σώμα και από το trailer (αν υπάρχει) και μπορεί να παραχωρήσει άδεια για να απαντηθεί. Σε αυτές τις περιπτώσεις, ο πυρήνας χρειάζεται απλώς να περάσει το μήνυμα από μια εργασία στην άλλη.
Ένα trailer είναι πληροφορίες που προστίθενται στο μήνυμα από τον πυρήνα (δεν μπορεί να οριστεί από τον χρήστη) οι οποίες μπορούν να ζητηθούν κατά την παραλαβή του μηνύματος με τις σημαίες MACH_RCV_TRAILER_<trailer_opt>
(υπάρχουν διαφορετικές πληροφορίες που μπορούν να ζητηθούν).
Ωστόσο, υπάρχουν και άλλα πιο πολύπλοκα μηνύματα, όπως αυτά που περνούν επιπλέον δικαιώματα θύρας ή μοιράζονται μνήμη, όπου ο πυρήνας χρειάζεται επίσης να στείλει αυτά τα αντικείμενα στον παραλήπτη. Σε αυτές τις περιπτώσεις, το πιο σημαντικό bit της κεφαλίδας msgh_bits
είναι ρυθμισμένο.
Οι δυνατές περιγραφές που μπορούν να περαστούν ορίζονται στο mach/message.h
:
In 32bits, όλοι οι περιγραφείς είναι 12B και ο τύπος του περιγραφέα είναι στον 11ο. Στα 64 bits, οι διαστάσεις ποικίλλουν.
Ο πυρήνας θα αντιγράψει τους περιγραφείς από μια εργασία στην άλλη αλλά πρώτα δημιουργώντας ένα αντίγραφο στη μνήμη του πυρήνα. Αυτή η τεχνική, γνωστή ως "Feng Shui", έχει καταχραστεί σε πολλές εκμεταλλεύσεις για να κάνει τον πυρήνα να αντιγράψει δεδομένα στη μνήμη του, κάνοντάς τον διαδικασία να στείλει περιγραφείς στον εαυτό της. Στη συνέχεια, η διαδικασία μπορεί να λάβει τα μηνύματα (ο πυρήνας θα τα απελευθερώσει).
Είναι επίσης δυνατό να σταλεί δικαίωμα θύρας σε μια ευάλωτη διαδικασία, και τα δικαιώματα θύρας θα εμφανιστούν απλώς στη διαδικασία (ακόμα κι αν δεν τα χειρίζεται).
Σημειώστε ότι οι θύρες σχετίζονται με το namespace της εργασίας, οπότε για να δημιουργήσετε ή να αναζητήσετε μια θύρα, το namespace της εργασίας ερωτάται επίσης (περισσότερα στο mach/mach_port.h
):
mach_port_allocate
| mach_port_construct
: Δημιουργία μιας θύρας.
mach_port_allocate
μπορεί επίσης να δημιουργήσει ένα σύνολο θυρών: δικαίωμα λήψης πάνω από μια ομάδα θυρών. Όποτε λαμβάνεται ένα μήνυμα, υποδεικνύεται η θύρα από την οποία προήλθε.
mach_port_allocate_name
: Αλλάξτε το όνομα της θύρας (κατά προεπιλογή 32bit ακέραιος)
mach_port_names
: Λάβετε ονόματα θυρών από έναν στόχο
mach_port_type
: Λάβετε δικαιώματα μιας εργασίας πάνω σε ένα όνομα
mach_port_rename
: Μετονομάστε μια θύρα (όπως το dup2 για FDs)
mach_port_allocate
: Κατανείμετε μια νέα ΛΗΨΗ, PORT_SET ή DEAD_NAME
mach_port_insert_right
: Δημιουργήστε ένα νέο δικαίωμα σε μια θύρα όπου έχετε ΛΗΨΗ
mach_port_...
mach_msg
| mach_msg_overwrite
: Λειτουργίες που χρησιμοποιούνται για να στείλουν και να λάβουν mach μηνύματα. Η έκδοση overwrite επιτρέπει να καθορίσετε ένα διαφορετικό buffer για τη λήψη μηνυμάτων (η άλλη έκδοση θα το επαναχρησιμοποιήσει απλώς).
Καθώς οι λειτουργίες mach_msg
και mach_msg_overwrite
είναι αυτές που χρησιμοποιούνται για να στείλουν και να λάβουν μηνύματα, η ρύθμιση ενός breakpoint σε αυτές θα επιτρέψει την επιθεώρηση των αποσταλμένων και ληφθέντων μηνυμάτων.
Για παράδειγμα, ξεκινήστε την αποσφαλμάτωση οποιασδήποτε εφαρμογής μπορείτε να αποσφαλματώσετε καθώς θα φορτώσει libSystem.B
που θα χρησιμοποιήσει αυτή τη λειτουργία.
Για να λάβετε τα επιχειρήματα του mach_msg
, ελέγξτε τους καταχωρητές. Αυτά είναι τα επιχειρήματα (από mach/message.h):
Λάβετε τις τιμές από τα μητρώα:
Επιθεωρήστε την κεφαλίδα του μηνύματος ελέγχοντας το πρώτο επιχείρημα:
Αυτός ο τύπος mach_msg_bits_t
είναι πολύ κοινός για να επιτρέπει μια απάντηση.
Το name είναι το προεπιλεγμένο όνομα που δίνεται στην θύρα (ελέγξτε πώς αυξάνεται στα πρώτα 3 bytes). Το ipc-object
είναι ο αποκρυπτογραφημένος μοναδικός ταυτοποιητής της θύρας.
Σημειώστε επίσης πώς οι θύρες με μόνο send
δικαίωμα αναγνωρίζουν τον κάτοχό τους (όνομα θύρας + pid).
Σημειώστε επίσης τη χρήση του +
για να υποδείξετε άλλες εργασίες που συνδέονται με την ίδια θύρα.
Είναι επίσης δυνατό να χρησιμοποιήσετε procesxp για να δείτε επίσης τα καταχωρημένα ονόματα υπηρεσιών (με το SIP απενεργοποιημένο λόγω της ανάγκης του com.apple.system-task-port
):
Μπορείτε να εγκαταστήσετε αυτό το εργαλείο σε iOS κατεβάζοντάς το από http://newosxbook.com/tools/binpack64-256.tar.gz
Σημειώστε πώς ο αποστολέας κατανέμει μια θύρα, δημιουργεί ένα δικαίωμα αποστολής για το όνομα org.darlinghq.example
και το στέλνει στον διακομιστή εκκίνησης ενώ ο αποστολέας ζήτησε το δικαίωμα αποστολής αυτού του ονόματος και το χρησιμοποίησε για να στείλει ένα μήνυμα.
Υπάρχουν μερικές ειδικές θύρες που επιτρέπουν να εκτελούνται ορισμένες ευαίσθητες ενέργειες ή να αποκτάται πρόσβαση σε ορισμένα ευαίσθητα δεδομένα σε περίπτωση που μια εργασία έχει τα SEND δικαιώματα πάνω τους. Αυτό καθιστά αυτές τις θύρες πολύ ενδιαφέρουσες από την προοπτική ενός επιτιθέμενου, όχι μόνο λόγω των δυνατοτήτων αλλά και επειδή είναι δυνατό να μοιραστούν τα SEND δικαιώματα μεταξύ εργασιών.
Αυτές οι θύρες εκπροσωπούνται από έναν αριθμό.
SEND δικαιώματα μπορούν να αποκτηθούν καλώντας host_get_special_port
και RECEIVE δικαιώματα καλώντας host_set_special_port
. Ωστόσο, και οι δύο κλήσεις απαιτούν την host_priv
θύρα, στην οποία μπορεί να έχει πρόσβαση μόνο ο root. Επιπλέον, στο παρελθόν, ο root μπορούσε να καλέσει host_set_special_port
και να καταλάβει αυθαίρετα, κάτι που επέτρεπε, για παράδειγμα, την παράκαμψη των υπογραφών κώδικα καταλαμβάνοντας την HOST_KEXTD_PORT
(το SIP τώρα το αποτρέπει).
Αυτές χωρίζονται σε 2 ομάδες: Οι πρώτες 7 θύρες ανήκουν στον πυρήνα και είναι η 1 HOST_PORT
, η 2 HOST_PRIV_PORT
, η 3 HOST_IO_MASTER_PORT
και η 7 είναι HOST_MAX_SPECIAL_KERNEL_PORT
.
Αυτές που ξεκινούν από τον αριθμό 8 ανήκουν σε συστήματα δαίμονες και μπορούν να βρεθούν δηλωμένες στο host_special_ports.h
.
Host port: Αν μια διαδικασία έχει SEND προνόμιο πάνω σε αυτή τη θύρα, μπορεί να αποκτήσει πληροφορίες σχετικά με το σύστημα καλώντας τις ρουτίνες της όπως:
host_processor_info
: Λάβετε πληροφορίες επεξεργαστή
host_info
: Λάβετε πληροφορίες host
host_virtual_physical_table_info
: Πίνακας εικονικής/φυσικής μνήμης (απαιτεί MACH_VMDEBUG)
host_statistics
: Λάβετε στατιστικά στοιχεία host
mach_memory_info
: Λάβετε διάταξη μνήμης πυρήνα
Host Priv port: Μια διαδικασία με SEND δικαίωμα πάνω σε αυτή τη θύρα μπορεί να εκτελέσει προνομιακές ενέργειες όπως να εμφανίσει δεδομένα εκκίνησης ή να προσπαθήσει να φορτώσει μια επέκταση πυρήνα. Η διαδικασία πρέπει να είναι root για να αποκτήσει αυτή την άδεια.
Επιπλέον, για να καλέσει το API kext_request
απαιτείται να έχει άλλες εξουσιοδοτήσεις com.apple.private.kext*
που δίνονται μόνο σε δυαδικά αρχεία της Apple.
Άλλες ρουτίνες που μπορούν να κληθούν είναι:
host_get_boot_info
: Λάβετε machine_boot_info()
host_priv_statistics
: Λάβετε προνομιακά στατιστικά στοιχεία
vm_allocate_cpm
: Κατανομή Συνεχούς Φυσικής Μνήμης
host_processors
: Στείλτε δικαίωμα στους επεξεργαστές host
mach_vm_wire
: Κάντε τη μνήμη μόνιμη
Καθώς ο root μπορεί να έχει πρόσβαση σε αυτή την άδεια, θα μπορούσε να καλέσει host_set_[special/exception]_port[s]
για να καταλάβει τις ειδικές ή εξαιρετικές θύρες host.
Είναι δυνατό να δει κανείς όλες τις ειδικές θύρες host εκτελώντας:
Αυτοί είναι οι θύρες που είναι κρατημένες για γνωστές υπηρεσίες. Είναι δυνατή η λήψη/ρύθμισή τους καλώντας task_[get/set]_special_port
. Μπορούν να βρεθούν στο task_special_ports.h
:
From here:
TASK_KERNEL_PORT[task-self send right]: Η θύρα που χρησιμοποιείται για τον έλεγχο αυτής της εργασίας. Χρησιμοποιείται για την αποστολή μηνυμάτων που επηρεάζουν την εργασία. Αυτή είναι η θύρα που επιστρέφεται από mach_task_self (βλ. Θύρες Εργασίας παρακάτω).
TASK_BOOTSTRAP_PORT[bootstrap send right]: Η θύρα εκκίνησης της εργασίας. Χρησιμοποιείται για την αποστολή μηνυμάτων που ζητούν την επιστροφή άλλων θυρών υπηρεσιών συστήματος.
TASK_HOST_NAME_PORT[host-self send right]: Η θύρα που χρησιμοποιείται για την αίτηση πληροφοριών σχετικά με τον περιέχοντα υπολογιστή. Αυτή είναι η θύρα που επιστρέφεται από mach_host_self.
TASK_WIRED_LEDGER_PORT[ledger send right]: Η θύρα που ονομάζει την πηγή από την οποία αυτή η εργασία αντλεί τη μνήμη πυρήνα που είναι συνδεδεμένη.
TASK_PAGED_LEDGER_PORT[ledger send right]: Η θύρα που ονομάζει την πηγή από την οποία αυτή η εργασία αντλεί τη μνήμη που διαχειρίζεται από προεπιλογή.
Αρχικά, το Mach δεν είχε "διεργασίες", είχε "εργασίες" που θεωρούνταν περισσότερο σαν ένα δοχείο νημάτων. Όταν το Mach συγχωνεύθηκε με το BSD κάθε εργασία συσχετίστηκε με μια διαδικασία BSD. Επομένως, κάθε διαδικασία BSD έχει τις λεπτομέρειες που χρειάζεται για να είναι διαδικασία και κάθε εργασία Mach έχει επίσης τις εσωτερικές της λειτουργίες (εκτός από το ανύπαρκτο pid 0 που είναι το kernel_task
).
Υπάρχουν δύο πολύ ενδιαφέρουσες συναρτήσεις που σχετίζονται με αυτό:
task_for_pid(target_task_port, pid, &task_port_of_pid)
: Λάβετε ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ για την θύρα εργασίας της εργασίας που σχετίζεται με το καθορισμένο από το pid
και δώστε το στην υποδεικνυόμενη target_task_port
(η οποία είναι συνήθως η εργασία καλούντος που έχει χρησιμοποιήσει το mach_task_self()
, αλλά θα μπορούσε να είναι μια θύρα ΑΠΟΣΤΟΛΗΣ σε μια διαφορετική εργασία).
pid_for_task(task, &pid)
: Δεδομένου ενός ΔΙΚΑΙΩΜΑΤΟΣ ΑΠΟΣΤΟΛΗΣ σε μια εργασία, βρείτε σε ποιο PID σχετίζεται αυτή η εργασία.
Για να εκτελέσει ενέργειες εντός της εργασίας, η εργασία χρειάστηκε ένα SEND
δικαίωμα στον εαυτό της καλώντας το mach_task_self()
(το οποίο χρησιμοποιεί το task_self_trap
(28)). Με αυτή την άδεια, μια εργασία μπορεί να εκτελέσει πολλές ενέργειες όπως:
task_threads
: Λάβετε ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ σε όλες τις θύρες εργασίας των νημάτων της εργασίας
task_info
: Λάβετε πληροφορίες σχετικά με μια εργασία
task_suspend/resume
: Αναστείλετε ή επαναφέρετε μια εργασία
task_[get/set]_special_port
thread_create
: Δημιουργήστε ένα νήμα
task_[get/set]_state
: Ελέγξτε την κατάσταση της εργασίας
και περισσότερα μπορούν να βρεθούν στο mach/task.h
Σημειώστε ότι με ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ σε μια θύρα εργασίας μιας διαφορετικής εργασίας, είναι δυνατό να εκτελούνται τέτοιες ενέργειες σε μια διαφορετική εργασία.
Επιπλέον, η θύρα_port είναι επίσης η vm_map
θύρα που επιτρέπει να διαβάσετε και να χειριστείτε τη μνήμη μέσα σε μια εργασία με συναρτήσεις όπως vm_read()
και vm_write()
. Αυτό σημαίνει βασικά ότι μια εργασία με δικαιώματα ΑΠΟΣΤΟΛΗΣ στη θύρα_port μιας διαφορετικής εργασίας θα είναι σε θέση να εισάγει κώδικα σε αυτή την εργασία.
Θυμηθείτε ότι επειδή ο πυρήνας είναι επίσης μια εργασία, αν κάποιος καταφέρει να αποκτήσει ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ πάνω στο kernel_task
, θα είναι σε θέση να κάνει τον πυρήνα να εκτελέσει οτιδήποτε (jailbreaks).
Καλέστε το mach_task_self()
για να λάβετε το όνομα για αυτή τη θύρα για την εργασία καλούντος. Αυτή η θύρα κληρονομείται μόνο μέσω του exec()
; μια νέα εργασία που δημιουργείται με το fork()
αποκτά μια νέα θύρα εργασίας (ως ειδική περίπτωση, μια εργασία αποκτά επίσης μια νέα θύρα εργασίας μετά το exec()
σε ένα εκτελέσιμο suid). Ο μόνος τρόπος για να δημιουργήσετε μια εργασία και να αποκτήσετε τη θύρα της είναι να εκτελέσετε τον "χορό ανταλλαγής θυρών" ενώ κάνετε ένα fork()
.
Αυτές είναι οι περιορισμοί για την πρόσβαση στη θύρα (από το macos_task_policy
από το εκτελέσιμο AppleMobileFileIntegrity
):
Εάν η εφαρμογή έχει com.apple.security.get-task-allow
δικαίωμα οι διαδικασίες από τον ίδιο χρήστη μπορούν να έχουν πρόσβαση στη θύρα εργασίας (συνήθως προστίθεται από το Xcode για αποσφαλμάτωση). Η διαδικασία πιστοποίησης δεν θα το επιτρέψει σε παραγωγικές εκδόσεις.
Οι εφαρμογές με το com.apple.system-task-ports
δικαίωμα μπορούν να αποκτήσουν τη θύρα εργασίας για οποιαδήποτε διαδικασία, εκτός από τον πυρήνα. Σε παλαιότερες εκδόσεις ονομαζόταν task_for_pid-allow
. Αυτό χορηγείται μόνο σε εφαρμογές της Apple.
Ο Root μπορεί να έχει πρόσβαση σε θύρες εργασίας εφαρμογών που δεν έχουν μεταγλωττιστεί με σκληρή εκτέλεση (και όχι από την Apple).
Η θύρα ονόματος εργασίας: Μια μη προνομιούχος έκδοση της θύρας εργασίας. Αναφέρεται στην εργασία, αλλά δεν επιτρέπει τον έλεγχο της. Το μόνο πράγμα που φαίνεται να είναι διαθέσιμο μέσω αυτής είναι το task_info()
.
Τα νήματα έχουν επίσης σχετικές θύρες, οι οποίες είναι ορατές από την εργασία που καλεί το task_threads
και από τον επεξεργαστή με processor_set_threads
. Ένα ΔΙΚΑΙΩΜΑ ΑΠΟΣΤΟΛΗΣ στη θύρα νήματος επιτρέπει τη χρήση της συνάρτησης από το υποσύστημα thread_act
, όπως:
thread_terminate
thread_[get/set]_state
act_[get/set]_state
thread_[suspend/resume]
thread_info
...
Κάθε νήμα μπορεί να αποκτήσει αυτή τη θύρα καλώντας το mach_thread_sef
.
Μπορείτε να αποκτήσετε ένα shellcode από:
Introduction to ARM64v8Συγκεντρώστε το προηγούμενο πρόγραμμα και προσθέστε τα entitlements για να μπορείτε να εισάγετε κώδικα με τον ίδιο χρήστη (αν όχι, θα χρειαστεί να χρησιμοποιήσετε sudo).