macOS XPC
Grundinformationen
XPC, was für XNU (den von macOS verwendeten Kernel) Inter-Prozess-Kommunikation steht, ist ein Framework für Kommunikation zwischen Prozessen auf macOS und iOS. XPC bietet einen Mechanismus für sichere, asynchrone Methodenaufrufe zwischen verschiedenen Prozessen im System. Es ist Teil von Apples Sicherheitsparadigma und ermöglicht die Erstellung von privilegierten Anwendungen, bei denen jede Komponente nur mit den Berechtigungen läuft, die sie benötigt, um ihre Aufgabe zu erfüllen, wodurch der potenzielle Schaden durch einen kompromittierten Prozess begrenzt wird.
XPC verwendet eine Form der Inter-Prozess-Kommunikation (IPC), die eine Reihe von Methoden umfasst, mit denen verschiedene Programme, die auf demselben System ausgeführt werden, Daten hin und her senden können.
Die wichtigsten Vorteile von XPC sind:
Sicherheit: Durch die Trennung der Arbeit in verschiedene Prozesse kann jedem Prozess nur die Berechtigung gewährt werden, die er benötigt. Das bedeutet, dass selbst wenn ein Prozess kompromittiert wird, er nur begrenzte Möglichkeiten hat, Schaden anzurichten.
Stabilität: XPC hilft, Abstürze auf die Komponente zu isolieren, in der sie auftreten. Wenn ein Prozess abstürzt, kann er neu gestartet werden, ohne den Rest des Systems zu beeinträchtigen.
Leistung: XPC ermöglicht eine einfache Parallelität, da verschiedene Aufgaben gleichzeitig in verschiedenen Prozessen ausgeführt werden können.
Der einzige Nachteil ist, dass die Trennung einer Anwendung in mehrere Prozesse, die über XPC kommunizieren, weniger effizient ist. Aber in heutigen Systemen ist dies kaum bemerkbar und die Vorteile überwiegen.
Anwendungsspezifische XPC-Dienste
Die XPC-Komponenten einer Anwendung befinden sich innerhalb der Anwendung selbst. Zum Beispiel finden Sie sie in /Applications/Safari.app/Contents/XPCServices
. Sie haben die Erweiterung .xpc
(wie com.apple.Safari.SandboxBroker.xpc
) und sind auch Bundles mit der Haupt-Binärdatei darin: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker
und eine Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist
Wie Sie vielleicht denken, wird eine XPC-Komponente andere Berechtigungen und Privilegien haben als die anderen XPC-Komponenten oder die Hauptanwendungs-Binärdatei. AUSGENOMMEN, wenn ein XPC-Dienst mit JoinExistingSession auf „Wahr“ in seiner Info.plist-Datei konfiguriert ist. In diesem Fall wird der XPC-Dienst in der gleichen Sicherheits-Sitzung wie die Anwendung ausgeführt, die ihn aufgerufen hat.
XPC-Dienste werden von launchd gestartet, wenn sie benötigt werden, und heruntergefahren, sobald alle Aufgaben abgeschlossen sind, um Systemressourcen freizugeben. Anwendungsspezifische XPC-Komponenten können nur von der Anwendung genutzt werden, wodurch das Risiko im Zusammenhang mit potenziellen Sicherheitsanfälligkeiten verringert wird.
Systemweite XPC-Dienste
Systemweite XPC-Dienste sind für alle Benutzer zugänglich. Diese Dienste, entweder launchd oder Mach-Typ, müssen in plist-Dateien definiert werden, die sich in bestimmten Verzeichnissen wie /System/Library/LaunchDaemons
, /Library/LaunchDaemons
, /System/Library/LaunchAgents
oder /Library/LaunchAgents
befinden.
Diese plist-Dateien haben einen Schlüssel namens MachServices
mit dem Namen des Dienstes und einen Schlüssel namens Program
mit dem Pfad zur Binärdatei:
Die in LaunchDameons
sind unter root aktiv. Wenn ein unprivilegierter Prozess mit einem dieser kommunizieren kann, könnte er in der Lage sein, Privilegien zu eskalieren.
XPC-Objekte
xpc_object_t
Jede XPC-Nachricht ist ein Dictionary-Objekt, das die Serialisierung und Deserialisierung vereinfacht. Darüber hinaus deklariert libxpc.dylib
die meisten Datentypen, sodass es möglich ist, sicherzustellen, dass die empfangenen Daten vom erwarteten Typ sind. In der C-API ist jedes Objekt ein xpc_object_t
(und sein Typ kann mit xpc_get_type(object)
überprüft werden).
Darüber hinaus kann die Funktion xpc_copy_description(object)
verwendet werden, um eine stringbasierte Darstellung des Objekts zu erhalten, die für Debugging-Zwecke nützlich sein kann.
Diese Objekte haben auch einige Methoden, die aufgerufen werden können, wie xpc_<object>_copy
, xpc_<object>_equal
, xpc_<object>_hash
, xpc_<object>_serialize
, xpc_<object>_deserialize
...
Die xpc_object_t
werden durch den Aufruf der Funktion xpc_<objetType>_create
erstellt, die intern _xpc_base_create(Class, Size)
aufruft, wobei der Typ der Klasse des Objekts (einer von XPC_TYPE_*
) und die Größe angegeben werden. (Es werden einige zusätzliche 40B zur Größe für Metadaten hinzugefügt). Das bedeutet, dass die Daten des Objekts bei der Offset von 40B beginnen.
Daher ist der xpc_<objectType>_t
eine Art Unterklasse von xpc_object_t
, die eine Unterklasse von os_object_t*
wäre.
Beachten Sie, dass es der Entwickler sein sollte, der xpc_dictionary_[get/set]_<objectType>
verwendet, um den Typ und den tatsächlichen Wert eines Schlüssels zu erhalten oder festzulegen.
xpc_pipe
Ein xpc_pipe
ist ein FIFO-Rohr, das Prozesse zur Kommunikation verwenden können (die Kommunikation verwendet Mach-Nachrichten).
Es ist möglich, einen XPC-Server zu erstellen, indem xpc_pipe_create()
oder xpc_pipe_create_from_port()
aufgerufen wird, um ihn mit einem bestimmten Mach-Port zu erstellen. Um Nachrichten zu empfangen, ist es möglich, xpc_pipe_receive
und xpc_pipe_try_receive
aufzurufen.
Beachten Sie, dass das xpc_pipe
-Objekt ein xpc_object_t
mit Informationen in seiner Struktur über die beiden verwendeten Mach-Ports und den Namen (falls vorhanden) ist. Der Name, zum Beispiel, der Daemon secinitd
in seiner plist /System/Library/LaunchDaemons/com.apple.secinitd.plist
konfiguriert das Rohr mit dem Namen com.apple.secinitd
.
Ein Beispiel für ein xpc_pipe
ist das Bootstrap-Pipe, das von launchd
erstellt wird und das Teilen von Mach-Ports ermöglicht.
NSXPC*
Dies sind Objective-C-Objekte auf hoher Ebene, die die Abstraktion von XPC-Verbindungen ermöglichen. Darüber hinaus ist es einfacher, diese Objekte mit DTrace zu debuggen als die vorherigen.
GCD Queues
XPC verwendet GCD, um Nachrichten zu übermitteln, außerdem generiert es bestimmte Dispatch-Warteschlangen wie xpc.transactionq
, xpc.io
, xpc-events.add-listenerq
, xpc.service-instance
...
XPC-Dienste
Dies sind Bundles mit der Erweiterung .xpc
, die sich im XPCServices
-Ordner anderer Projekte befinden und in der Info.plist
den CFBundlePackageType
auf XPC!
gesetzt haben.
Diese Datei hat andere Konfigurationsschlüssel wie ServiceType
, die Application, User, System oder _SandboxProfile
sein können, die einen Sandbox oder _AllowedClients
definieren können, die Berechtigungen oder IDs angeben könnten, die erforderlich sind, um den Dienst zu kontaktieren. Diese und andere Konfigurationsoptionen sind nützlich, um den Dienst beim Start zu konfigurieren.
Starten eines Dienstes
Die App versucht, sich mit einem XPC-Dienst zu verbinden, indem sie xpc_connection_create_mach_service
verwendet, dann lokalisiert launchd den Daemon und startet xpcproxy
. xpcproxy
setzt die konfigurierten Einschränkungen durch und startet den Dienst mit den bereitgestellten FDs und Mach-Ports.
Um die Geschwindigkeit der Suche nach dem XPC-Dienst zu verbessern, wird ein Cache verwendet.
Es ist möglich, die Aktionen von xpcproxy
zu verfolgen mit:
Die XPC-Bibliothek verwendet kdebug
, um Aktionen zu protokollieren, indem xpc_ktrace_pid0
und xpc_ktrace_pid1
aufgerufen werden. Die verwendeten Codes sind nicht dokumentiert, daher müssen sie in /usr/share/misc/trace.codes
hinzugefügt werden. Sie haben das Präfix 0x29
und zum Beispiel ist einer 0x29000004
: XPC_serializer_pack
.
Das Dienstprogramm xpcproxy
verwendet das Präfix 0x22
, zum Beispiel: 0x2200001c: xpcproxy:will_do_preexec
.
XPC-Ereignisnachrichten
Anwendungen können sich für verschiedene Ereignis-nachrichten anmelden, sodass sie auf Abruf initiiert werden können, wenn solche Ereignisse eintreten. Die Einrichtung für diese Dienste erfolgt in launchd plist-Dateien, die sich in den gleichen Verzeichnissen wie die vorherigen befinden und einen zusätzlichen LaunchEvent
-Schlüssel enthalten.
XPC Verbindungsprozessprüfung
Wenn ein Prozess versucht, eine Methode über eine XPC-Verbindung aufzurufen, sollte der XPC-Dienst überprüfen, ob dieser Prozess berechtigt ist, sich zu verbinden. Hier sind die gängigen Methoden zur Überprüfung und die häufigen Fallstricke:
XPC-Autorisierung
Apple erlaubt es auch, dass Apps einige Rechte konfigurieren und wie man sie erhält, sodass, wenn der aufrufende Prozess diese hat, er berechtigt wäre, eine Methode vom XPC-Dienst aufzurufen:
XPC-Sniffer
Um die XPC-Nachrichten abzuhören, können Sie xpcspy verwenden, das Frida nutzt.
Ein weiteres mögliches Werkzeug ist XPoCe2.
XPC-Kommunikation C-Codebeispiel
XPC-Kommunikation Objective-C Codebeispiel
Client innerhalb eines Dylb-Codes
Remote XPC
Diese Funktionalität, die von RemoteXPC.framework
(aus libxpc
) bereitgestellt wird, ermöglicht die Kommunikation über XPC zwischen verschiedenen Hosts.
Die Dienste, die Remote XPC unterstützen, haben in ihrer plist den Schlüssel UsesRemoteXPC, wie es bei /System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist
der Fall ist. Allerdings wird der Dienst, obwohl er mit launchd
registriert ist, von UserEventAgent
mit den Plugins com.apple.remoted.plugin
und com.apple.remoteservicediscovery.events.plugin
bereitgestellt.
Darüber hinaus ermöglicht das RemoteServiceDiscovery.framework
, Informationen vom com.apple.remoted.plugin
abzurufen, das Funktionen wie get_device
, get_unique_device
, connect
... bereitstellt.
Sobald connect
verwendet wird und der Socket fd
des Dienstes gesammelt wird, ist es möglich, die Klasse remote_xpc_connection_*
zu verwenden.
Es ist möglich, Informationen über Remote-Dienste mit dem CLI-Tool /usr/libexec/remotectl
unter Verwendung von Parametern wie:
Die Kommunikation zwischen BridgeOS und dem Host erfolgt über eine dedizierte IPv6-Schnittstelle. Das MultiverseSupport.framework
ermöglicht es, Sockets zu erstellen, deren fd
für die Kommunikation verwendet wird.
Es ist möglich, diese Kommunikationen mit netstat
, nettop
oder der Open-Source-Option netbottom
zu finden.
Last updated