macOS MIG - Mach Interface Generator
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)
MIG δημιουργήθηκε για να απλοποιήσει τη διαδικασία δημιουργίας κώδικα Mach IPC. Βασικά παράγει τον απαραίτητο κώδικα για να επικοινωνούν ο διακομιστής και ο πελάτης με μια δεδομένη ορισμό. Ακόμα και αν ο παραγόμενος κώδικας είναι άσχημος, ένας προγραμματιστής θα χρειαστεί απλώς να τον εισάγει και ο κώδικάς του θα είναι πολύ πιο απλός από πριν.
Ο ορισμός καθορίζεται στη Γλώσσα Ορισμού Διεπαφής (IDL) χρησιμοποιώντας την επέκταση .defs
.
Αυτοί οι ορισμοί έχουν 5 ενότητες:
Δήλωση υποσυστήματος: Η λέξη-κλειδί subsystem χρησιμοποιείται για να υποδείξει το όνομα και το id. Είναι επίσης δυνατή η σήμανση ως KernelServer
αν ο διακομιστής πρέπει να εκτελείται στον πυρήνα.
Συμπεριλήψεις και εισαγωγές: Το MIG χρησιμοποιεί τον προεπεξεργαστή C, επομένως μπορεί να χρησιμοποιεί εισαγωγές. Επιπλέον, είναι δυνατή η χρήση uimport
και simport
για κώδικα που παράγεται από χρήστη ή διακομιστή.
Δηλώσεις τύπων: Είναι δυνατή η ορισμός τύπων δεδομένων αν και συνήθως θα εισάγει mach_types.defs
και std_types.defs
. Για προσαρμοσμένους τύπους μπορεί να χρησιμοποιηθεί κάποια σύνταξη:
[in/out]tran
: Συνάρτηση που πρέπει να μεταφραστεί από ένα εισερχόμενο ή σε ένα εξερχόμενο μήνυμα
c[user/server]type
: Χαρτογράφηση σε άλλο τύπο C.
destructor
: Καλέστε αυτή τη συνάρτηση όταν ο τύπος απελευθερωθεί.
Λειτουργίες: Αυτές είναι οι ορισμοί των μεθόδων RPC. Υπάρχουν 5 διαφορετικοί τύποι:
routine
: Αναμένει απάντηση
simpleroutine
: Δεν αναμένει απάντηση
procedure
: Αναμένει απάντηση
simpleprocedure
: Δεν αναμένει απάντηση
function
: Αναμένει απάντηση
Δημιουργήστε ένα αρχείο ορισμού, σε αυτή την περίπτωση με μια πολύ απλή συνάρτηση:
Σημειώστε ότι το πρώτο επιχείρημα είναι η θύρα για δέσμευση και το MIG θα χειριστεί αυτόματα τη θύρα απάντησης (εκτός αν καλέσετε mig_get_reply_port()
στον κωδικό του πελάτη). Επιπλέον, το ID των λειτουργιών θα είναι διαδοχικό ξεκινώντας από το υποσύστημα ID που υποδεικνύεται (έτσι αν μια λειτουργία είναι απαρχαιωμένη, διαγράφεται και χρησιμοποιείται το skip
για να χρησιμοποιηθεί ακόμα το ID της).
Τώρα χρησιμοποιήστε το MIG για να δημιουργήσετε τον κωδικό του διακομιστή και του πελάτη που θα είναι σε θέση να επικοινωνούν μεταξύ τους για να καλέσουν τη λειτουργία Αφαίρεση:
Πολλά νέα αρχεία θα δημιουργηθούν στον τρέχοντα φάκελο.
Μπορείτε να βρείτε ένα πιο σύνθετο παράδειγμα στο σύστημά σας με: mdfind mach_port.defs
Και μπορείτε να το μεταγλωττίσετε από τον ίδιο φάκελο με το αρχείο με: mig -DLIBSYSCALL_INTERFACE mach_ports.defs
Στα αρχεία myipcServer.c
και myipcServer.h
μπορείτε να βρείτε την δήλωση και τον ορισμό της δομής SERVERPREFmyipc_subsystem
, η οποία βασικά ορίζει τη λειτουργία που θα καλέσετε με βάση το αναγνωριστικό μηνύματος που ελήφθη (υποδείξαμε έναν αρχικό αριθμό 500):
Βασισμένη στην προηγούμενη δομή, η συνάρτηση myipc_server_routine
θα πάρει το ID μηνύματος και θα επιστρέψει τη σωστή συνάρτηση για κλήση:
Σε αυτό το παράδειγμα έχουμε ορίσει μόνο 1 συνάρτηση στις ορισμοί, αλλά αν είχαμε ορίσει περισσότερες συναρτήσεις, θα ήταν μέσα στον πίνακα του SERVERPREFmyipc_subsystem
και η πρώτη θα είχε ανατεθεί στο ID 500, η δεύτερη στο ID 501...
Αν η συνάρτηση αναμενόταν να στείλει μια reply, η συνάρτηση mig_internal kern_return_t __MIG_check__Reply__<name>
θα υπήρχε επίσης.
Στην πραγματικότητα, είναι δυνατόν να προσδιοριστεί αυτή η σχέση στη δομή subsystem_to_name_map_myipc
από το myipcServer.h
(subsystem_to_name_map_***
σε άλλα αρχεία):
Τέλος, μια άλλη σημαντική λειτουργία για να λειτουργήσει ο διακομιστής θα είναι myipc_server
, η οποία είναι αυτή που θα καλέσει τη συνάρτηση που σχετίζεται με το ληφθέν id:
Ελέγξτε τις προηγουμένως επισημασμένες γραμμές που αποκτούν πρόσβαση στη συνάρτηση για να καλέσουν με ID.
Ακολουθεί ο κώδικας για τη δημιουργία ενός απλού διακομιστή και πελάτη όπου ο πελάτης μπορεί να καλέσει τις συναρτήσεις Subtract από τον διακομιστή:
Το NDR_record εξάγεται από το libsystem_kernel.dylib
, και είναι μια δομή που επιτρέπει στο MIG να μετατρέπει δεδομένα ώστε να είναι ανεξάρτητα από το σύστημα στο οποίο χρησιμοποιείται, καθώς το MIG σχεδιάστηκε για να χρησιμοποιείται μεταξύ διαφορετικών συστημάτων (και όχι μόνο στην ίδια μηχανή).
Αυτό είναι ενδιαφέρον γιατί αν το _NDR_record
βρεθεί σε ένα δυαδικό αρχείο ως εξάρτηση (jtool2 -S <binary> | grep NDR
ή nm
), σημαίνει ότι το δυαδικό αρχείο είναι πελάτης ή διακομιστής MIG.
Επιπλέον, οι διακομιστές MIG έχουν τον πίνακα διανομής στο __DATA.__const
(ή στο __CONST.__constdata
στον πυρήνα macOS και __DATA_CONST.__const
σε άλλους πυρήνες *OS). Αυτό μπορεί να αποθηκευτεί με jtool2
.
Και οι πελάτες MIG θα χρησιμοποιήσουν το __NDR_record
για να στείλουν με __mach_msg
στους διακομιστές.
Καθώς πολλά δυαδικά αρχεία χρησιμοποιούν τώρα το MIG για να εκθέσουν mach ports, είναι ενδιαφέρον να γνωρίζουμε πώς να εντοπίσουμε ότι χρησιμοποιήθηκε το MIG και τις λειτουργίες που εκτελεί το MIG με κάθε ID μηνύματος.
jtool2 μπορεί να αναλύσει πληροφορίες MIG από ένα δυαδικό Mach-O υποδεικνύοντας το ID μηνύματος και προσδιορίζοντας τη λειτουργία που πρέπει να εκτελεστεί:
Επιπλέον, οι συναρτήσεις MIG είναι απλώς περιτυλίγματα της πραγματικής συνάρτησης που καλείται, πράγμα που σημαίνει ότι αν αποκτήσετε την αποσυναρμολόγησή της και κάνετε grep για BL, ίσως μπορέσετε να βρείτε την πραγματική συνάρτηση που καλείται:
Αναφέρθηκε προηγουμένως ότι η συνάρτηση που θα φροντίσει για την κλήση της σωστής συνάρτησης ανάλογα με το αναγνωριστικό μηνύματος που ελήφθη ήταν η myipc_server
. Ωστόσο, συνήθως δεν θα έχετε τα σύμβολα του δυαδικού (χωρίς ονόματα συναρτήσεων), οπότε είναι ενδιαφέρον να ελέγξετε πώς φαίνεται αποσυμπιεσμένο καθώς θα είναι πάντα πολύ παρόμοιο (ο κώδικας αυτής της συνάρτησης είναι ανεξάρτητος από τις εκτεθειμένες συναρτήσεις):
Στην πραγματικότητα, αν πάτε στη συνάρτηση 0x100004000
θα βρείτε τον πίνακα των routine_descriptor
δομών. Το πρώτο στοιχείο της δομής είναι η διεύθυνση όπου η συνάρτηση είναι υλοποιημένη, και η δομή καταλαμβάνει 0x28 bytes, οπότε κάθε 0x28 bytes (ξεκινώντας από το byte 0) μπορείτε να πάρετε 8 bytes και αυτό θα είναι η διεύθυνση της συνάρτησης που θα κληθεί:
Αυτά τα δεδομένα μπορούν να εξαχθούν χρησιμοποιώντας αυτό το σενάριο Hopper.
Ο κώδικας που παράγεται από το MIG καλεί επίσης το kernel_debug
για να δημιουργήσει αρχεία καταγραφής σχετικά με τις λειτουργίες κατά την είσοδο και έξοδο. Είναι δυνατή η εξέταση τους χρησιμοποιώντας trace
ή kdv
: kdv all | grep MIG
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)