# macOS XPC
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) ! * Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Informations de base XPC, qui signifie Communication inter-processus XNU (le noyau utilisé par macOS), est un framework pour la **communication entre processus** sur macOS et iOS. XPC fournit un mécanisme pour effectuer des **appels de méthode asynchrones et sécurisés entre différents processus** du système. Il fait partie du paradigme de sécurité d'Apple, permettant la **création d'applications avec des privilèges séparés** où chaque **composant** s'exécute avec **seulement les autorisations nécessaires** pour effectuer son travail, limitant ainsi les dommages potentiels d'un processus compromis. XPC utilise une forme de communication inter-processus (IPC), qui est un ensemble de méthodes permettant à différents programmes s'exécutant sur le même système d'échanger des données. Les principaux avantages de XPC sont les suivants : 1. **Sécurité** : En séparant le travail en différents processus, chaque processus peut se voir accorder uniquement les autorisations dont il a besoin. Cela signifie que même si un processus est compromis, il a une capacité limitée à causer des dommages. 2. **Stabilité** : XPC contribue à isoler les plantages dans le composant où ils se produisent. Si un processus plante, il peut être redémarré sans affecter le reste du système. 3. **Performance** : XPC permet une concurrence facile, car différentes tâches peuvent être exécutées simultanément dans différents processus. Le seul **inconvénient** est que **séparer une application en plusieurs processus** qui communiquent via XPC est **moins efficace**. Mais dans les systèmes d'aujourd'hui, cela est presque imperceptible et les avantages sont meilleurs. ## Services XPC spécifiques à l'application Les composants XPC d'une application se trouvent **à l'intérieur de l'application elle-même**. Par exemple, dans Safari, vous pouvez les trouver dans **`/Applications/Safari.app/Contents/XPCServices`**. Ils ont l'extension **`.xpc`** (comme **`com.apple.Safari.SandboxBroker.xpc`**) et sont **également des bundles** avec le binaire principal à l'intérieur : `/Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker` et un fichier `Info.plist : /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist` Comme vous pouvez le penser, un **composant XPC aura des autorisations et des privilèges différents** des autres composants XPC ou du binaire principal de l'application. SAUF si un service XPC est configuré avec [**JoinExistingSession**](https://developer.apple.com/documentation/bundleresources/information\_property\_list/xpcservice/joinexistingsession) défini sur "True" dans son fichier **Info.plist**. Dans ce cas, le service XPC s'exécutera dans la **même session de sécurité que l'application** qui l'a appelé. Les services XPC sont **démarrés** par **launchd** lorsque cela est nécessaire et **arrêtés** une fois que toutes les tâches sont **terminées** pour libérer les ressources système. Les composants XPC spécifiques à l'application ne peuvent être utilisés que par l'application, réduisant ainsi les risques liés aux vulnérabilités potentielles. ## Services XPC à l'échelle du système Les services XPC à l'échelle du système sont accessibles à tous les utilisateurs. Ces services, qu'ils soient de type launchd ou Mach, doivent être **définis dans des fichiers plist** situés dans des répertoires spécifiés tels que **`/System/Library/LaunchDaemons`**, **`/Library/LaunchDaemons`**, **`/System/Library/LaunchAgents`** ou **`/Library/LaunchAgents`**. Ces fichiers plist auront une clé appelée **`MachServices`** avec le nom du service, et une clé appelée **`Program`** avec le chemin vers le binaire : ```xml cat /Library/LaunchDaemons/com.jamf.management.daemon.plist Program /Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon AbandonProcessGroup KeepAlive Label com.jamf.management.daemon MachServices com.jamf.management.daemon.aad com.jamf.management.daemon.agent com.jamf.management.daemon.binary com.jamf.management.daemon.selfservice com.jamf.management.daemon.service RunAtLoad ``` Ceux dans **`LaunchDameons`** sont exécutés par root. Donc, si un processus non privilégié peut communiquer avec l'un d'entre eux, il pourrait être en mesure d'escalader les privilèges. ## Messages d'événement XPC Les applications peuvent **s'abonner** à différents **messages d'événement**, ce qui leur permet d'être **initiées à la demande** lorsque de tels événements se produisent. La **configuration** de ces services est effectuée dans des fichiers **plist de launchd**, situés dans les **mêmes répertoires que les précédents** et contenant une clé supplémentaire **`LaunchEvent`**. ### Vérification du processus de connexion XPC Lorsqu'un processus essaie d'appeler une méthode via une connexion XPC, le **service XPC doit vérifier si ce processus est autorisé à se connecter**. Voici les moyens courants de vérifier cela et les pièges courants : {% content-ref url="macos-xpc-connecting-process-check.md" %} [macos-xpc-connecting-process-check.md](macos-xpc-connecting-process-check.md) {% endcontent-ref %} ## Autorisation XPC Apple permet également aux applications de **configurer certains droits et la manière de les obtenir**, de sorte que si le processus appelant les possède, il serait **autorisé à appeler une méthode** du service XPC : {% content-ref url="macos-xpc-authorization.md" %} [macos-xpc-authorization.md](macos-xpc-authorization.md) {% endcontent-ref %} ## Exemple de code C {% tabs %} {% tab title="xpc_server.c" %} ```c // gcc xpc_server.c -o xpc_server #include static void handle_event(xpc_object_t event) { if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { // Print received message const char* received_message = xpc_dictionary_get_string(event, "message"); printf("Received message: %s\n", received_message); // Create a response dictionary xpc_object_t response = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(response, "received", "received"); // Send response xpc_connection_t remote = xpc_dictionary_get_remote_connection(event); xpc_connection_send_message(remote, response); // Clean up xpc_release(response); } } static void handle_connection(xpc_connection_t connection) { xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { handle_event(event); }); xpc_connection_resume(connection); } int main(int argc, const char *argv[]) { xpc_connection_t service = xpc_connection_create_mach_service("xyz.hacktricks.service", dispatch_get_main_queue(), XPC_CONNECTION_MACH_SERVICE_LISTENER); if (!service) { fprintf(stderr, "Failed to create service.\n"); exit(EXIT_FAILURE); } xpc_connection_set_event_handler(service, ^(xpc_object_t event) { xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_CONNECTION) { handle_connection(event); } }); xpc_connection_resume(service); dispatch_main(); return 0; } ``` ```c #include #include int main(int argc, const char * argv[]) { xpc_connection_t connection = xpc_connection_create_mach_service("com.apple.securityd", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_DICTIONARY) { const char *description = xpc_dictionary_get_string(event, "description"); printf("Received event: %s\n", description); } }); xpc_connection_resume(connection); sleep(10); xpc_release(connection); return 0; } ``` {% endtab %} {% tab title="xpc_server.c" %} ```c // gcc xpc_client.c -o xpc_client #include int main(int argc, const char *argv[]) { xpc_connection_t connection = xpc_connection_create_mach_service("xyz.hacktricks.service", NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) { // Print received message const char* received_message = xpc_dictionary_get_string(event, "received"); printf("Received message: %s\n", received_message); } }); xpc_connection_resume(connection); xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_string(message, "message", "Hello, Server!"); xpc_connection_send_message(connection, message); dispatch_main(); return 0; } ``` {% tab title="xyz.hacktricks.service.plist" %} ```xml Label xyz.hacktricks.service MachServices xyz.hacktricks.service Program /tmp/xpc_server ProgramArguments /tmp/xpc_server ``` {% endtab %} {% endtabs %} ```bash # Compile the server & client gcc xpc_server.c -o xpc_server gcc xpc_client.c -o xpc_client # Save server on it's location cp xpc_server /tmp # Load daemon sudo cp xyz.hacktricks.service.plist /Library/LaunchDaemons sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.service.plist # Call client ./xpc_client # Clean sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.service.plist sudo rm /Library/LaunchDaemons/xyz.hacktricks.service.plist /tmp/xpc_server ``` ## Exemple de code Objective-C {% tabs %} {% tab title="oc_xpc_server.m" %} ```objectivec // gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server #include @protocol MyXPCProtocol - (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply; @end @interface MyXPCObject : NSObject @end @implementation MyXPCObject - (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply { NSLog(@"Received message: %@", some_string); NSString *response = @"Received"; reply(response); } @end @interface MyDelegate : NSObject @end @implementation MyDelegate - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection { newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)]; MyXPCObject *my_object = [MyXPCObject new]; newConnection.exportedObject = my_object; [newConnection resume]; return YES; } @end int main(void) { NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:@"xyz.hacktricks.svcoc"]; id delegate = [MyDelegate new]; listener.delegate = delegate; [listener resume]; sleep(10); // Fake something is done and then it ends } ``` {% tab title="oc_xpc_client.m" %} ```objectivec // gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client #include @protocol MyXPCProtocol - (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply; @end int main(void) { NSXPCConnection *connection = [[NSXPCConnection alloc] initWithMachServiceName:@"xyz.hacktricks.svcoc" options:NSXPCConnectionPrivileged]; connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)]; [connection resume]; [[connection remoteObjectProxy] sayHello:@"Hello, Server!" withReply:^(NSString *response) { NSLog(@"Received response: %@", response); }]; [[NSRunLoop currentRunLoop] run]; return 0; } ``` {% tab title="xyz.hacktricks.svcoc.plist" %} ```xml Label xyz.hacktricks.svcoc MachServices xyz.hacktricks.svcoc Program /tmp/oc_xpc_server ProgramArguments /tmp/oc_xpc_server ``` {% endtab %} {% endtabs %} ```bash # Compile the server & client gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client # Save server on it's location cp oc_xpc_server /tmp # Load daemon sudo cp xyz.hacktricks.svcoc.plist /Library/LaunchDaemons sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist # Call client ./oc_xpc_client # Clean sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist sudo rm /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist /tmp/oc_xpc_server ``` ## Client à l'intérieur d'un code Dylb The client code is responsible for establishing a connection with the server and sending requests to it. In the case of a Dylb code, the client is embedded within the code itself, allowing for seamless communication between the client and the server. Le code client est responsable d'établir une connexion avec le serveur et d'envoyer des requêtes à celui-ci. Dans le cas d'un code Dylb, le client est intégré directement dans le code lui-même, permettant une communication fluide entre le client et le serveur. To implement a client inside a Dylb code, you can use the following steps: Pour mettre en place un client à l'intérieur d'un code Dylb, vous pouvez suivre les étapes suivantes : 1. Import the necessary libraries or modules required for establishing a network connection. Importez les bibliothèques ou modules nécessaires pour établir une connexion réseau. 2. Define the server's IP address and port number to establish a connection. Définissez l'adresse IP et le numéro de port du serveur pour établir une connexion. 3. Create a socket object to establish a connection with the server. Créez un objet socket pour établir une connexion avec le serveur. 4. Use the socket object to send requests to the server. Utilisez l'objet socket pour envoyer des requêtes au serveur. 5. Receive and process the server's response. Recevez et traitez la réponse du serveur. Here is an example of client code inside a Dylb code: Voici un exemple de code client à l'intérieur d'un code Dylb : ```python import socket # Define server IP address and port number server_ip = "192.168.0.1" server_port = 1234 # Create a socket object client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Establish a connection with the server client_socket.connect((server_ip, server_port)) # Send requests to the server client_socket.send(b"Hello, server!") # Receive and process the server's response response = client_socket.recv(1024) print(response.decode()) # Close the connection client_socket.close() ``` In this example, the client code establishes a TCP connection with the server at the specified IP address and port number. It sends a "Hello, server!" message to the server and receives the server's response, which is then printed on the console. Finally, the connection is closed. Dans cet exemple, le code client établit une connexion TCP avec le serveur à l'adresse IP et au numéro de port spécifiés. Il envoie un message "Hello, server!" au serveur et reçoit la réponse du serveur, qui est ensuite affichée sur la console. Enfin, la connexion est fermée. ```objectivec // gcc -dynamiclib -framework Foundation oc_xpc_client.m -o oc_xpc_client.dylib // gcc injection example: // DYLD_INSERT_LIBRARIES=oc_xpc_client.dylib /path/to/vuln/bin #import @protocol MyXPCProtocol - (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply; @end __attribute__((constructor)) static void customConstructor(int argc, const char **argv) { NSString* _serviceName = @"xyz.hacktricks.svcoc"; NSXPCConnection* _agentConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:4096]; [_agentConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)]]; [_agentConnection resume]; [[_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error) { (void)error; NSLog(@"Connection Failure"); }] sayHello:@"Hello, Server!" withReply:^(NSString *response) { NSLog(@"Received response: %@", response); } ]; NSLog(@"Done!"); return; } ```
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? Ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) ! * Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).