macOS IPC - Inter Process Communication
Mach poruke putem portova
Osnovne informacije
Mach koristi taskove kao najmanju jedinicu za deljenje resursa, pri čemu svaki task može sadržati više niti. Ovi taskovi i niti su mapirani 1:1 na POSIX procese i niti.
Komunikacija između taskova se odvija putem Mach Inter-Process Communication (IPC), koristeći jednosmjerne komunikacione kanale. Poruke se prenose između portova, koji deluju kao vrste redova poruka upravljanih od strane jezgra.
Port je osnovni element Mach IPC-a. Može se koristiti za slanje poruka i za njihovo primanje.
Svaki proces ima IPC tabelu, u kojoj je moguće pronaći mach portove procesa. Ime mach porta zapravo predstavlja broj (pokazivač na jezgrovni objekat).
Proces takođe može poslati ime porta sa određenim pravima drugom tasku i jezgro će napraviti ovaj unos u IPC tabeli drugog taska.
Prava na portu
Prava na portu, koja definišu koje operacije task može izvršiti, ključne su za ovu komunikaciju. Moguća prava na portu su (definicije odavde):
Pravo na primanje, koje omogućava primanje poruka poslatih na port. Mach portovi su MPSC (multiple-producer, single-consumer) redovi, što znači da može postojati samo jedno pravo na primanje za svaki port u celom sistemu (za razliku od cevi, gde više procesa može držati deskriptore fajlova za kraj za čitanje jedne cevi).
Task sa pravom na primanje može primati poruke i kreirati prava na slanje, omogućavajući mu slanje poruka. Originalno, samo sopstveni task ima pravo na primanje nad svojim portom.
Ako vlasnik prava na primanje umre ili ga ubije, pravo na slanje postaje beskorisno (mrtvo ime).
Pravo na slanje, koje omogućava slanje poruka na port.
Pravo na slanje se može klonirati tako da task koji poseduje pravo na slanje može klonirati pravo i dodeliti ga trećem tasku.
Imajte na umu da se prava na portu takođe mogu prosleđivati putem Mac poruka.
Pravo na jednokratno slanje, koje omogućava slanje jedne poruke na port i zatim nestaje.
Ovo pravo ne može biti klonirano, ali se može premestiti.
Pravo na set portova, koje označava set portova umesto pojedinačnog porta. Skidanje poruke sa seta portova skida poruku sa jednog od portova koje sadrži. Set portova se može koristiti za osluškivanje više portova istovremeno, slično kao
select
/poll
/epoll
/kqueue
u Unix-u.Mrtvo ime, koje nije stvarno pravo na portu, već samo rezervacija. Kada se port uništi, sva postojeća prava na portu postaju mrtva imena.
Taskovi mogu preneti SEND prava drugima, omogućavajući im da pošalju poruke nazad. SEND prava takođe mogu biti klonirana, tako da task može duplicirati pravo i dati ga trećem tasku. Ovo, zajedno sa posredničkim procesom poznatim kao bootstrap server, omogućava efikasnu komunikaciju između taskova.
Portovi fajlova
Portovi fajlova omogućavaju da se deskriptori fajlova enkapsuliraju u Mac portove (koristeći prava na Mach portovima). Moguće je kreirati fileport
od datog FD koristeći fileport_makeport
i kreirati FD iz fileporta koristeći fileport_makefd
.
Uspostavljanje komunikacije
Kao što je ranije pomenuto, moguće je slati prava korišćenjem Mach poruka, međutim, ne možete poslati pravo bez već postojećeg prava za slanje Mach poruke. Kako se onda uspostavlja prva komunikacija?
Za to je uključen bootstrap server (launchd na Mac-u), pošto svako može dobiti SEND pravo ka bootstrap serveru, moguće je zatražiti od njega pravo da pošalje poruku drugom procesu:
Task A kreira novi port, dobijajući pravo na primanje nad njim.
Task A, kao vlasnik prava na primanje, generiše SEND pravo za port.
Task A uspostavlja vezu sa bootstrap serverom, i šalje mu SEND pravo za port koji je generisao na početku.
Zapamtite da svako može dobiti SEND pravo ka bootstrap serveru.
Task A šalje
bootstrap_register
poruku bootstrap serveru da poveže dati port sa imenom kao što jecom.apple.taska
Task B interaguje sa bootstrap serverom da izvrši bootstrap pretragu za imenom servisa (
bootstrap_lookup
). Da bi bootstrap server mogao da odgovori, task B će mu poslati SEND pravo ka portu koji je prethodno kreirao unutar poruke pretrage. Ako je pretraga uspešna, server duplira SEND pravo primljeno od Task A i prebacuje ga Task B.
Zapamtite da svako može dobiti SEND pravo ka bootstrap serveru.
Sa ovim SEND pravom, Task B je sposoban da pošalje poruku Task A-i.
Za dvosmernu komunikaciju obično task B generiše novi port sa pravom na primanje i pravom na slanje, i daje pravo na slanje Task A-i kako bi mogao slati poruke TASK B-u (dvosmerna komunikacija).
Bootstrap server ne može autentifikovati ime servisa koje tvrdi task. Ovo znači da bi task potencijalno mogao predstavljati bilo koji sistemski task, kao što je lažno tvrditi ime autorizacionog servisa a zatim odobriti svaki zahtev.
Zatim, Apple čuva imena servisa koje pruža sistem u sigurnim konfiguracionim fajlovima, smeštenim u SIP-zaštićenim direktorijumima: /System/Library/LaunchDaemons
i /System/Library/LaunchAgents
. Pored svakog imena servisa, takođe je sačuvana povezana binarna datoteka. Bootstrap server će kreirati i držati pravo na primanje za svako od ovih imena servisa.
Za ove unapred definisane servise, proces pretrage se malo razlikuje. Kada se traži ime servisa, launchd pokreće servis dinamički. Novi tok rada je sledeći:
Task B pokreće bootstrap pretragu za imenom servisa.
launchd proverava da li je task pokrenut i ako nije, ga pokreće.
Task A (servis) izvršava bootstrap check-in (
bootstrap_check_in()
). Ovde, bootstrap server kreira SEND pravo, zadržava ga, i prebacuje pravo na primanje Task A-i.launchd duplira SEND pravo i šalje ga Task B-u.
Task B generiše novi port sa pravom na primanje i pravom na slanje, i daje pravo na slanje Task A-i (servisu) kako bi mogao slati poruke TASK B-u (dvosmerna komunikacija).
Međutim, ovaj proces se odnosi samo na unapred definisane sistemski taskove. Ne-sistemski taskovi i dalje funkcionišu kao što je opisano originalno, što potencijalno može omogućiti predstavljanje.
Stoga, launchd nikada ne bi trebalo da se sruši ili će se ceo sistem srušiti.
Mach poruka
Funkcija mach_msg
, suštinski sistemski poziv, koristi se za slanje i primanje Mach poruka. Funkcija zahteva da poruka bude poslata kao početni argument. Ova poruka mora početi sa strukturom mach_msg_header_t
, praćenom stvarnim sadržajem poruke. Struktura je definisana na sledeći način:
Procesi koji poseduju pravo na prijem mogu primati poruke na Mach portu. Nasuprot tome, pošiljaoci imaju pravo na slanje ili jednokratno slanje. Pravo jednokratnog slanja je isključivo za slanje jedne poruke, nakon čega postaje nevažeće.
Početno polje msgh_bits
je mapa bitova:
Prvi bit (najznačajniji) se koristi za označavanje da je poruka kompleksna (više o tome ispod)
i 4. bit se koriste od strane jezgra
5 najmanje značajnih bitova 2. bajta mogu se koristiti za vaučer: druga vrsta porta za slanje kombinacija ključ/vrednost.
5 najmanje značajnih bitova 3. bajta mogu se koristiti za lokalni port
5 najmanje značajnih bitova 4. bajta mogu se koristiti za udaljeni port
Tipovi koji se mogu navesti u vaučeru, lokalnim i udaljenim portovima su (iz mach/message.h):
Na primer, MACH_MSG_TYPE_MAKE_SEND_ONCE
može se koristiti da ukazuje da bi trebalo izvesti i preneti jednokratno slanje prava za ovaj port. Takođe se može specificirati MACH_PORT_NULL
da bi se sprečilo da primalac može da odgovori.
Da bi se postigla jednostavna dvosmerna komunikacija, proces može specificirati mach port u mach zaglavlju poruke nazvan reply port (msgh_local_port
) gde primalac poruke može poslati odgovor na ovu poruku.
Imajte na umu da se ovakva vrsta dvosmerne komunikacije koristi u XPC porukama koje očekuju odgovor (xpc_connection_send_message_with_reply
i xpc_connection_send_message_with_reply_sync
). Ali obično se kreiraju različiti portovi kako je objašnjeno ranije da bi se kreirala dvosmerna komunikacija.
Ostala polja zaglavlja poruke su:
msgh_size
: veličina celog paketa.msgh_remote_port
: port preko kojeg je poslata ova poruka.msgh_voucher_port
: mach vaučeri.msgh_id
: ID ove poruke, koji se tumači od strane primaoca.
Imajte na umu da se mach poruke šalju preko mach porta
, koji je kanal komunikacije sa jednim primaocem, više pošiljalaca ugrađen u mach kernel. Više procesa može slati poruke ka mach portu, ali u svakom trenutku samo jedan proces može čitati iz njega.
Poruke se zatim formiraju mach_msg_header_t
zaglavljem praćenim telom i trailerom (ako postoji) i može dozvoliti odgovor na nju. U tim slučajevima, kernel samo treba da prosledi poruku iz jednog zadatka u drugi.
Trailer je informacija dodata poruci od strane kernela (ne može je postaviti korisnik) koja se može zatražiti prilikom prijema poruke sa zastavicom MACH_RCV_TRAILER_<trailer_opt>
(postoji različite informacije koje se mogu zatražiti).
Kompleksne Poruke
Međutim, postoje i druge kompleksnije poruke, poput onih koje prenose dodatna prava porta ili dele memoriju, gde kernel takođe mora da pošalje ove objekte primaocu. U ovim slučajevima, najznačajniji bit zaglavlja msgh_bits
je postavljen.
Mogući deskriptori za prenos su definisani u mach/message.h
:
U 32-bitnom sistemu, svi deskriptori su 12B i tip deskriptora je u 11. U 64-bitnom sistemu, veličine variraju.
Kernel će kopirati deskriptore iz jednog zadatka u drugi, ali prvo kreira kopiju u kernel memoriji. Ova tehnika, poznata kao "Feng Shui", zloupotrebljena je u nekoliko eksploatacija kako bi naterala kernel da kopira podatke u svojoj memoriji, omogućavajući procesu da pošalje deskriptore sebi. Zatim proces može primati poruke (kernel će ih osloboditi).
Takođe je moguće poslati prava porta ranjivom procesu, i prava porta će se jednostavno pojaviti u procesu (čak i ako ih ne obrađuje).
Mac Ports API
Imajte na umu da su portovi povezani sa imenikom zadatka, pa prilikom kreiranja ili pretrage porta, takođe se pretražuje imenik zadatka (više u mach/mach_port.h
):
mach_port_allocate
|mach_port_construct
: Kreirajte port.mach_port_allocate
takođe može kreirati skup portova: primi pravo preko grupe portova. Svaki put kada se primi poruka, naznačen je port sa kog je poslata.mach_port_allocate_name
: Promenite ime porta (podrazumevano 32-bitni ceo broj)mach_port_names
: Dobijanje imena porta iz ciljamach_port_type
: Dobijanje prava zadatka nad imenommach_port_rename
: Preimenovanje porta (kao dup2 za FD-ove)mach_port_allocate
: Alociranje novog PRIMANJA, SKUPA_PORTOVA ili MRTVOG_IMENAmach_port_insert_right
: Kreiranje novog prava u portu gde imate PRIMANJEmach_port_...
mach_msg
|mach_msg_overwrite
: Funkcije korišćene za slanje i primanje mach poruka. Verzija za prepisivanje omogućava da se navede drugi bafer za prijem poruke (druga verzija će ga samo ponovo koristiti).
Debug mach_msg
Pošto su funkcije mach_msg
i mach_msg_overwrite
one koje se koriste za slanje i primanje poruka, postavljanje prekidača na njih omogućilo bi inspekciju poslatih i primljenih poruka.
Na primer, počnite sa debagovanjem bilo koje aplikacije koju možete da debagujete jer će učitati libSystem.B
koja će koristiti ovu funkciju.
Da biste dobili argumente mach_msg
, proverite registre. Ovo su argumenti (iz mach/message.h):
Dobijanje vrednosti iz registara:
Pregledajte zaglavlje poruke proveravajući prvi argument:
Taj tip mach_msg_bits_t
je vrlo čest kako bi omogućio odgovor.
Nabroj portove
Ime je podrazumevano ime dodeljeno portu (proverite kako se povećava u prva 3 bajta). ipc-object
je zamagljeni jedinstveni identifikator porta.
Takođe obratite pažnju kako portovi sa samo send
pravom identifikuju vlasnika (ime porta + pid).
Takođe obratite pažnju na upotrebu +
za označavanje drugih zadataka povezanih sa istim portom.
Takođe je moguće koristiti procesxp da biste videli i registrovana imena servisa (sa onemogućenim SIP-om zbog potrebe za com.apple.system-task-port
):
Možete instalirati ovaj alat u iOS preuzimanjem sa http://newosxbook.com/tools/binpack64-256.tar.gz
Primer koda
Obratite pažnju kako pošiljalac dodeljuje port, kreira send right za ime org.darlinghq.example
i šalje ga bootstrap serveru dok je pošiljalac zatražio send right za to ime i koristio ga je da pošalje poruku.
Privilegovani portovi
Postoje neki posebni portovi koji omogućavaju izvođenje određenih osetljivih radnji ili pristup određenim osetljivim podacima u slučaju da zadaci imaju dozvole za slanje (SEND) nad njima. Ovo čini ove portove vrlo zanimljivim iz perspektive napadača ne samo zbog mogućnosti već i zato što je moguće deliti dozvole za slanje između zadataka.
Specijalni portovi domaćina
Ovi portovi su predstavljeni brojevima.
Prava za SLANJE (SEND) mogu se dobiti pozivanjem host_get_special_port
i prava za PRIJEM (RECEIVE) pozivanjem host_set_special_port
. Međutim, oba poziva zahtevaju host_priv
port koji samo korisnik sa privilegijama može pristupiti. Osim toga, u prošlosti je korisnik sa privilegijama mogao pozvati host_set_special_port
i preuzeti proizvoljne koji su omogućavali na primer zaobilaženje potpisa koda preuzimanjem HOST_KEXTD_PORT
(SIP sada sprečava ovo).
Ovi portovi su podeljeni u 2 grupe: Prvih 7 portova su u vlasništvu jezgra pri čemu je 1 HOST_PORT
, 2 HOST_PRIV_PORT
, 3 HOST_IO_MASTER_PORT
, a 7 je HOST_MAX_SPECIAL_KERNEL_PORT
.
Oni koji počinju od broja 8 su u vlasništvu sistemskih demona i mogu se pronaći deklarisani u host_special_ports.h
.
Host port: Ako proces ima privilegiju za slanje (SEND) nad ovim portom, može dobiti informacije o sistemu pozivanjem njegovih rutina poput:
host_processor_info
: Dobijanje informacija o procesoruhost_info
: Dobijanje informacija o domaćinuhost_virtual_physical_table_info
: Virtuelna/fizička tabela stranica (zahteva MACH_VMDEBUG)host_statistics
: Dobijanje statistika domaćinamach_memory_info
: Dobijanje rasporeda memorije jezgraHost Priv port: Proces sa pravom za slanje (SEND) nad ovim portom može izvršiti privilegovane radnje poput prikazivanja podataka o pokretanju ili pokušaja učitavanja proširenja jezgra. Proces mora biti root da bi dobio ove dozvole.
Osim toga, da bi se pozvao
kext_request
API, potrebno je imati druge privilegijecom.apple.private.kext*
koje se dodeljuju samo Apple binarnim datotekama.Druge rutine koje se mogu pozvati su:
host_get_boot_info
: Dobijanjemachine_boot_info()
host_priv_statistics
: Dobijanje privilegovanih statistikavm_allocate_cpm
: Alociranje kontinualne fizičke memorijehost_processors
: Pravo slanja host procesorimamach_vm_wire
: Čini memoriju rezidentnomPošto root može pristupiti ovim dozvolama, mogao bi pozvati
host_set_[special/exception]_port[s]
da preuzme specijalne ili izuzetne portove domaćina.
Moguće je videti sve specijalne portove domaćina pokretanjem:
Task Portovi
Originalno, Mach nije imao "procese", već "taskove" koji su se smatrali više kao kontejneri niti. Kada je Mach spojen sa BSD-om, svaki task je bio povezan sa BSD procesom. Stoga, svaki BSD proces ima detalje potrebne da bude proces, a svaki Mach task takođe ima svoje unutrašnje funkcije (osim nepostojećeg pid 0 koji je kernel_task
).
Postoje dve veoma interesantne funkcije u vezi sa tim:
task_for_pid(target_task_port, pid, &task_port_of_pid)
: Dobijanje SEND prava za task port taska povezanog sa određenimpid
-om i davanje toga port-a naznačenomtarget_task_port
-u (koji je obično task pozivaoca koji je koristiomach_task_self()
, ali može biti SEND port preko drugog taska.)pid_for_task(task, &pid)
: Dajući SEND pravo na task, pronađi sa kojim PID-om je taj task povezan.
Da bi izvršio radnje unutar taska, tasku je potrebno SEND
pravo na sebe pozivajući mach_task_self()
(koji koristi task_self_trap
(28)). Sa ovlašćenjem, task može izvršiti nekoliko radnji kao što su:
task_threads
: Dobijanje SEND prava nad svim task portovima niti taskatask_info
: Dobijanje informacija o taskutask_suspend/resume
: Pauziranje ili nastavljanje taskatask_[get/set]_special_port
thread_create
: Kreiranje nititask_[get/set]_state
: Kontrola stanja taskai još toga se može naći u mach/task.h
Primetite da sa SEND pravom nad task portom drugog taska, moguće je izvršiti takve radnje nad drugim taskom.
Osim toga, task_port je takođe port za vm_map
koji omogućava čitanje i manipulaciju memorijom unutar taska pomoću funkcija poput vm_read()
i vm_write()
. To u osnovi znači da će task sa SEND pravima nad task_portom drugog taska biti u mogućnosti da ubaci kod u taj task.
Zapamtite da je kernel takođe task, ako neko uspe da dobije SEND dozvole nad kernel_task
, biće u mogućnosti da natera kernel da izvrši bilo šta (jailbreaks).
Pozovi
mach_task_self()
da dobiješ ime za ovaj port za task pozivaoca. Ovaj port se nasleđuje samo prekoexec()
; novi task kreiran safork()
dobija novi task port (kao poseban slučaj, task takođe dobija novi task port nakonexec()
u suid binarnom fajlu). Jedini način da spawnuješ task i dobiješ njegov port je da izvedeš "ples sa zamjenom portova" dok radišfork()
.Ovo su ograničenja za pristup portu (iz
macos_task_policy
iz binarnog fajlaAppleMobileFileIntegrity
):Ako aplikacija ima dozvolu
com.apple.security.get-task-allow
, procesi od iste korisnika mogu pristupiti task portu (obično dodato od strane Xcode-a za debagovanje). Proces notarizacije neće dozvoliti ovo u produkcijskim verzijama.Aplikacije sa dozvolom
com.apple.system-task-ports
mogu dobiti task port za bilo koji proces, osim kernela. U starijim verzijama se nazivalotask_for_pid-allow
. Ovo je dozvoljeno samo Apple aplikacijama.Root može pristupiti task portovima aplikacija koje nisu kompajlirane sa hardened runtime-om (i ne od strane Apple-a).
Ime task porta: Neprivilegovana verzija task porta. Referiše na task, ali ne dozvoljava kontrolisanje istog. Jedina stvar koja se čini dostupnom kroz njega je task_info()
.
Ubacivanje Shell koda u nit putem Task porta
Možeš preuzeti shell kod sa:
pageIntroduction to ARM64v8macOS IPC (Inter-Process Communication)
Inter-process communication (IPC) mechanisms are commonly used in macOS applications to allow processes to communicate with each other. These mechanisms include Mach ports, XPC services, and distributed objects.
Mach Ports
Mach ports are low-level communication endpoints used by processes to send and receive messages. They are a fundamental part of the macOS operating system and are used extensively by system services and applications.
XPC Services
XPC services are a higher-level IPC mechanism provided by the XPC framework. They allow processes to create and manage lightweight services that can communicate with each other securely.
Distributed Objects
Distributed objects are another IPC mechanism that allows objects to be passed between processes. This mechanism is commonly used in macOS applications to share data and functionality between different parts of an application.
Understanding how these IPC mechanisms work is essential for both developers and security researchers to identify potential security vulnerabilities and prevent privilege escalation attacks.
macOS Process Abuse
macOS processes run with different levels of privileges, depending on the user account under which they are executed. Attackers can abuse processes running with higher privileges to escalate their own privileges and gain unauthorized access to sensitive system resources.
By exploiting vulnerabilities in macOS processes, attackers can execute arbitrary code, manipulate system settings, and access restricted files and data. Understanding how processes are managed and secured in macOS is crucial for defending against privilege escalation attacks.
macOS Security and Privilege Escalation
macOS provides various security mechanisms to protect system resources and prevent unauthorized access. These mechanisms include code signing, sandboxing, entitlements, and system integrity protection.
Code signing ensures that only trusted and verified code is executed on macOS systems, preventing the execution of malicious software. Sandboxing restricts the capabilities of applications, limiting their access to system resources.
Entitlements define the privileges that an application or process has on a macOS system. By carefully configuring entitlements, developers can restrict the actions that an application can perform, reducing the risk of privilege escalation.
System Integrity Protection (SIP) is a security feature that protects system files and directories from modification, even by processes running with root privileges. SIP prevents unauthorized changes to critical system components, enhancing the overall security of macOS systems.
Understanding these security mechanisms and how they interact is essential for securing macOS systems and preventing privilege escalation attacks. Regularly updating macOS systems and applications, configuring security settings, and monitoring system activity are crucial steps in maintaining the security of macOS devices.
Kompajlujte prethodni program i dodajte ovlašćenja kako biste mogli da ubacite kod sa istim korisnikom (ako ne, moraćete koristiti sudo).
Last updated