macOS IOKit
Basic Information
Το I/O Kit είναι ένα ανοιχτού κώδικα, αντικειμενοστραφές πλαίσιο οδηγών συσκευών στον πυρήνα XNU, που διαχειρίζεται δυναμικά φορτωμένους οδηγούς συσκευών. Επιτρέπει την προσθήκη αρθρωτού κώδικα στον πυρήνα εν κινήσει, υποστηρίζοντας ποικιλία υλικού.
Οι οδηγοί IOKit θα εξάγουν βασικά συναρτήσεις από τον πυρήνα. Οι τύποι παραμέτρων αυτών των συναρτήσεων είναι προκαθορισμένοι και επαληθεύονται. Επιπλέον, παρόμοια με το XPC, το IOKit είναι απλώς ένα άλλο επίπεδο πάνω από τα μηνύματα Mach.
Ο κώδικας IOKit XNU kernel είναι ανοιχτού κώδικα από την Apple στο https://github.com/apple-oss-distributions/xnu/tree/main/iokit. Επιπλέον, τα στοιχεία IOKit του χώρου χρηστών είναι επίσης ανοιχτού κώδικα https://github.com/opensource-apple/IOKitUser.
Ωστόσο, κανένας οδηγός IOKit δεν είναι ανοιχτού κώδικα. Ούτως ή άλλως, από καιρό σε καιρό μια έκδοση ενός οδηγού μπορεί να έρθει με σύμβολα που διευκολύνουν την αποσφαλμάτωσή του. Δείτε πώς να πάρετε τις επεκτάσεις οδηγών από το firmware εδώ.
Είναι γραμμένο σε C++. Μπορείτε να αποκτήσετε αποσυμβολισμένα σύμβολα C++ με:
Οι εκτεθειμένες συναρτήσεις του IOKit θα μπορούσαν να εκτελούν επιπλέον ελέγχους ασφαλείας όταν ένας πελάτης προσπαθεί να καλέσει μια συνάρτηση, αλλά σημειώστε ότι οι εφαρμογές είναι συνήθως περιορισμένες από το sandbox με το οποίο μπορούν να αλληλεπιδρούν οι συναρτήσεις του IOKit.
Οδηγοί
Στο macOS βρίσκονται σε:
/System/Library/Extensions
Αρχεία KEXT ενσωματωμένα στο λειτουργικό σύστημα OS X.
/Library/Extensions
Αρχεία KEXT που εγκαθίστανται από λογισμικό τρίτων
Στο iOS βρίσκονται σε:
/System/Library/Extensions
Μέχρι τον αριθμό 9, οι αναφερόμενοι οδηγοί είναι φορτωμένοι στη διεύθυνση 0. Αυτό σημαίνει ότι δεν είναι πραγματικοί οδηγοί αλλά μέρος του πυρήνα και δεν μπορούν να αποφορτωθούν.
Για να βρείτε συγκεκριμένες επεκτάσεις μπορείτε να χρησιμοποιήσετε:
Για να φορτώσετε και να ξεφορτώσετε επεκτάσεις πυρήνα, κάντε:
IORegistry
Το IORegistry είναι ένα κρίσιμο μέρος του πλαισίου IOKit στο macOS και iOS που λειτουργεί ως βάση δεδομένων για την αναπαράσταση της υλικής διαμόρφωσης και κατάστασης του συστήματος. Είναι μια ιεραρχική συλλογή αντικειμένων που αναπαριστούν όλο το υλικό και τους οδηγούς που έχουν φορτωθεί στο σύστημα, και τις σχέσεις τους μεταξύ τους.
Μπορείτε να αποκτήσετε το IORegistry χρησιμοποιώντας το cli ioreg
για να το επιθεωρήσετε από την κονσόλα (ιδιαίτερα χρήσιμο για iOS).
Μπορείτε να κατεβάσετε IORegistryExplorer
από τα Xcode Additional Tools από https://developer.apple.com/download/all/ και να επιθεωρήσετε το macOS IORegistry μέσω μιας γραφικής διεπαφής.
Στο IORegistryExplorer, οι "επίπεδοι" χρησιμοποιούνται για να οργανώσουν και να εμφανίσουν τις σχέσεις μεταξύ διαφορετικών αντικειμένων στο IORegistry. Κάθε επίπεδο αντιπροσωπεύει έναν συγκεκριμένο τύπο σχέσης ή μια συγκεκριμένη άποψη της υλικού και της διαμόρφωσης οδηγών του συστήματος. Ακολουθούν μερικοί από τους κοινούς επίπεδους που μπορεί να συναντήσετε στο IORegistryExplorer:
IOService Plane: Αυτό είναι το πιο γενικό επίπεδο, που εμφανίζει τα αντικείμενα υπηρεσιών που αντιπροσωπεύουν οδηγούς και nubs (κανάλια επικοινωνίας μεταξύ οδηγών). Δείχνει τις σχέσεις προμηθευτή-πελάτη μεταξύ αυτών των αντικειμένων.
IODeviceTree Plane: Αυτό το επίπεδο αντιπροσωπεύει τις φυσικές συνδέσεις μεταξύ συσκευών καθώς συνδέονται στο σύστημα. Χρησιμοποιείται συχνά για να οπτικοποιήσει την ιεραρχία των συσκευών που συνδέονται μέσω λεωφόρων όπως USB ή PCI.
IOPower Plane: Εμφανίζει αντικείμενα και τις σχέσεις τους σε όρους διαχείρισης ενέργειας. Μπορεί να δείξει ποια αντικείμενα επηρεάζουν την κατάσταση ενέργειας άλλων, χρήσιμο για την αποσφαλμάτωση προβλημάτων που σχετίζονται με την ενέργεια.
IOUSB Plane: Ειδικά επικεντρωμένο σε συσκευές USB και τις σχέσεις τους, δείχνοντας την ιεραρχία των USB hubs και των συνδεδεμένων συσκευών.
IOAudio Plane: Αυτό το επίπεδο είναι για την αναπαράσταση συσκευών ήχου και των σχέσεών τους εντός του συστήματος.
...
Driver Comm Code Example
Ο παρακάτω κώδικας συνδέεται με την υπηρεσία IOKit "YourServiceNameHere"
και καλεί τη συνάρτηση μέσα στον επιλεγέα 0. Για αυτό:
πρώτα καλεί
IOServiceMatching
καιIOServiceGetMatchingServices
για να αποκτήσει την υπηρεσία.Στη συνέχεια, καθορίζει μια σύνδεση καλώντας
IOServiceOpen
.Και τελικά καλεί μια συνάρτηση με
IOConnectCallScalarMethod
υποδεικνύοντας τον επιλεγέα 0 (ο επιλεγέας είναι ο αριθμός που έχει ανατεθεί στη συνάρτηση που θέλετε να καλέσετε).
Υπάρχουν άλλες συναρτήσεις που μπορούν να χρησιμοποιηθούν για να καλέσουν τις συναρτήσεις IOKit εκτός από IOConnectCallScalarMethod
όπως IOConnectCallMethod
, IOConnectCallStructMethod
...
Αντίστροφη μηχανική σημείου εισόδου οδηγού
Μπορείτε να τα αποκτήσετε αυτά για παράδειγμα από μια εικόνα firmware (ipsw). Στη συνέχεια, φορτώστε την στο αγαπημένο σας decompiler.
Μπορείτε να ξεκινήσετε την αποσυμπίεση της συνάρτησης externalMethod
καθώς αυτή είναι η συνάρτηση του οδηγού που θα δέχεται την κλήση και θα καλεί τη σωστή συνάρτηση:
Αυτή η απαίσια κλήση αποκαταστάθηκε σημαίνει:
Σημειώστε πώς στην προηγούμενη ορισμό λείπει η παράμετρος self
, η καλή ορισμός θα ήταν:
Στην πραγματικότητα, μπορείτε να βρείτε τον πραγματικό ορισμό στο https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388:
Με αυτές τις πληροφορίες μπορείτε να ξαναγράψετε Ctrl+Δεξί -> Edit function signature
και να ορίσετε τους γνωστούς τύπους:
Ο νέος αποσυμπιεσμένος κώδικας θα φαίνεται έτσι:
Για το επόμενο βήμα πρέπει να έχουμε ορίσει τη δομή IOExternalMethodDispatch2022
. Είναι ανοιχτού κώδικα στο https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176, μπορείτε να το ορίσετε:
Τώρα, ακολουθώντας το (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray
μπορείτε να δείτε πολλά δεδομένα:
Αλλάξτε τον Τύπο Δεδομένων σε IOExternalMethodDispatch2022:
μετά την αλλαγή:
Και όπως γνωρίζουμε εκεί έχουμε ένα πίνακα 7 στοιχείων (ελέγξτε τον τελικό αποσυμπιεσμένο κώδικα), κάντε κλικ για να δημιουργήσετε έναν πίνακα 7 στοιχείων:
Αφού δημιουργηθεί ο πίνακας, μπορείτε να δείτε όλες τις εξαγόμενες συναρτήσεις:
Αν θυμάστε, για να καλέσουμε μια εξαγόμενη συνάρτηση από τον χώρο χρήστη δεν χρειάζεται να καλέσουμε το όνομα της συνάρτησης, αλλά τον αριθμό επιλεγέα. Εδώ μπορείτε να δείτε ότι ο επιλεγέας 0 είναι η συνάρτηση initializeDecoder
, ο επιλεγέας 1 είναι startDecoder
, ο επιλεγέας 2 initializeEncoder
...
Last updated