macOS IOKit
Osnovne informacije
IO Kit je open-source, objektno orijentisani framework za drajvere uređaja u XNU jezgru, koji upravlja dinamički učitanim drajverima uređaja. Omogućava dodavanje modularnog koda u jezgro u hodu, podržavajući različit hardver.
IOKit drajveri će u osnovi izvoziti funkcije iz jezgra. Tipovi parametara ovih funkcija su unapred definisani i provereni. Osim toga, slično kao XPC, IOKit je samo još jedan sloj na vrhu Mach poruka.
IOKit XNU jezgro kod je otvoren od strane Apple-a na https://github.com/apple-oss-distributions/xnu/tree/main/iokit. Osim toga, IOKit komponente u korisničkom prostoru su takođe otvorenog koda https://github.com/opensource-apple/IOKitUser.
Međutim, nijedan IOKit drajver nije otvorenog koda. U svakom slučaju, povremeno izdanje drajvera može doći sa simbolima koji olakšavaju njegovo debagovanje. Pogledajte kako dobiti proširenja drajvera iz firmware-a ovde.**
Napisan je u C++. Možete dobiti demangle C++ simbole sa:
IOKit izložene funkcije mogu izvršiti dodatne sigurnosne provere kada klijent pokuša da pozove funkciju, ali imajte na umu da aplikacije obično su ograničene od strane peska-boksa sa kojim IOKit funkcijama mogu da interaguju.
Drajveri
U macOS-u se nalaze u:
/System/Library/Extensions
KEXT fajlovi ugrađeni u OS X operativni sistem.
/Library/Extensions
KEXT fajlovi instalirani od strane softvera trećih lica
U iOS-u se nalaze u:
/System/Library/Extensions
Do broja 9 navedeni drajveri su učitani na adresi 0. To znači da to nisu pravi drajveri već deo jezgra i ne mogu se istovremeno ukloniti.
Kako biste pronašli određene ekstenzije, možete koristiti:
Da biste učitali i isključili proširenja jezgra, uradite:
IORegistry
IORegistry je ključni deo IOKit okvira u macOS-u i iOS-u koji služi kao baza podataka za predstavljanje hardverske konfiguracije i stanja sistema. To je hijerarhijska kolekcija objekata koja predstavlja sav hardver i drajvere učitane na sistemu, kao i njihove međusobne odnose.
IORegistry možete dobiti koristeći CLI ioreg
kako biste ga pregledali sa konzole (posebno korisno za iOS).
Možete preuzeti IORegistryExplorer
iz Dodatnih alata za Xcode sa https://developer.apple.com/download/all/ i pregledati macOS IORegistry kroz grafički interfejs.
U IORegistryExplorer-u, "ravni" se koriste za organizovanje i prikaz odnosa između različitih objekata u IORegistry-ju. Svaka ravan predstavlja određenu vrstu odnosa ili određeni prikaz hardvera sistema i konfiguracije drajvera. Evo nekih od uobičajenih ravni sa kojima možete da se susretnete u IORegistryExplorer-u:
IOService Ravan: Ovo je najopštija ravan, koja prikazuje servisne objekte koji predstavljaju drajvere i nubove (kanale komunikacije između drajvera). Prikazuje odnose između pružalaca usluga i klijenata između ovih objekata.
IODeviceTree Ravan: Ova ravan predstavlja fizičke veze između uređaja kako su povezani sa sistemom. Često se koristi za vizualizaciju hijerarhije uređaja povezanih putem busova poput USB-a ili PCI-ja.
IOPower Ravan: Prikazuje objekte i njihove odnose u smislu upravljanja snagom. Može pokazati koji objekti utiču na stanje snage drugih, što je korisno za otklanjanje problema povezanih sa snagom.
IOUSB Ravan: Specifično fokusirana na USB uređaje i njihove odnose, prikazujući hijerarhiju USB hubova i povezanih uređaja.
IOAudio Ravan: Ova ravan služi za predstavljanje audio uređaja i njihovih odnosa unutar sistema.
...
Primer koda za komunikaciju sa drajverom
Sledeći kod se povezuje sa IOKit servisom "ImeVašegServisaOvde"
i poziva funkciju unutar selektora 0. Za to:
prvo poziva
IOServiceMatching
iIOServiceGetMatchingServices
da bi dobio servis.Zatim uspostavlja vezu pozivajući
IOServiceOpen
.I na kraju poziva funkciju sa
IOConnectCallScalarMethod
navodeći selektor 0 (selektor je broj koji je dodeljen funkciji koju želite da pozovete).
Postoje druge funkcije koje se mogu koristiti za pozivanje IOKit funkcija osim IOConnectCallScalarMethod
kao što su IOConnectCallMethod
, IOConnectCallStructMethod
...
Reversing driver entrypoint
Možete ih dobiti, na primer, iz firmver slike (ipsw). Zatim je učitajte u svoj omiljeni dekompajler.
Možete početi dekompajlirati funkciju externalMethod
jer je ovo funkcija drajvera koja će primati poziv i pozivati odgovarajuću funkciju:
Taj užasni poziv demangle znači:
Primetite kako je u prethodnoj definiciji propušten parametar self
, dobra definicija bi bila:
Zapravo, pravu definiciju možete pronaći na https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388:
Sa ovim informacijama možete prepraviti Ctrl+Desno -> Uredi potpis funkcije
i postaviti poznate tipove:
Novi dekompajlirani kod će izgledati ovako:
Za sledeći korak potrebno je da imamo definisanu strukturu IOExternalMethodDispatch2022
. To je otvorenog koda na https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176, možete je definisati:
Sada, prateći (IOExternalMethodDispatch2022 *)&sIOExternalMethodArray
možete videti puno podataka:
Promenite tip podataka u IOExternalMethodDispatch2022:
nakon promene:
I sada, pošto znamo da imamo niz od 7 elemenata (proverite konačni dekompajlirani kod), kliknite da biste kreirali niz od 7 elemenata:
Nakon što je niz kreiran, možete videti sve izvezene funkcije:
Ako se sećate, da biste pozvali izvezenu funkciju iz korisničkog prostora, ne morate nazvati funkciju, već broj selektora. Ovde možete videti da je selektor 0 funkcija initializeDecoder
, selektor 1 je startDecoder
, selektor 2 initializeEncoder
...
Last updated