mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 19:13:39 +00:00
412 lines
16 KiB
Markdown
412 lines
16 KiB
Markdown
# macOS XPC
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
Outras formas de apoiar o HackTricks:
|
|
|
|
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
|
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios do GitHub** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
|
|
## Informações Básicas
|
|
|
|
XPC, que significa XNU (o kernel usado pelo macOS) inter-Process Communication, é um framework para **comunicação entre processos** no macOS e iOS. O XPC fornece um mecanismo para realizar **chamadas de métodos seguras e assíncronas entre diferentes processos** no sistema. É parte do paradigma de segurança da Apple, permitindo a **criação de aplicações com separação de privilégios** onde cada **componente** executa com **apenas as permissões necessárias** para realizar seu trabalho, limitando assim o potencial dano de um processo comprometido.
|
|
|
|
O XPC usa uma forma de Comunicação Inter-Processos (IPC), que é um conjunto de métodos para diferentes programas em execução no mesmo sistema enviarem dados um para o outro.
|
|
|
|
Os principais benefícios do XPC incluem:
|
|
|
|
1. **Segurança**: Ao separar o trabalho em diferentes processos, cada processo pode ser concedido apenas as permissões de que precisa. Isso significa que mesmo que um processo seja comprometido, sua capacidade de causar danos é limitada.
|
|
2. **Estabilidade**: O XPC ajuda a isolar falhas no componente onde ocorrem. Se um processo falha, ele pode ser reiniciado sem afetar o restante do sistema.
|
|
3. **Desempenho**: O XPC permite fácil concorrência, pois diferentes tarefas podem ser executadas simultaneamente em diferentes processos.
|
|
|
|
A única **desvantagem** é que **separar uma aplicação em vários processos** fazendo-os comunicar via XPC é **menos eficiente**. Mas nos sistemas atuais isso quase não é perceptível e os benefícios são melhores.
|
|
|
|
## Serviços XPC Específicos de Aplicações
|
|
|
|
Os componentes XPC de uma aplicação estão **dentro da própria aplicação.** Por exemplo, no Safari você pode encontrá-los em **`/Applications/Safari.app/Contents/XPCServices`**. Eles têm a extensão **`.xpc`** (como **`com.apple.Safari.SandboxBroker.xpc`**) e são **também bundles** com o binário principal dentro dele: `/Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker` e um `Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist`
|
|
|
|
Como você deve estar pensando, um **componente XPC terá diferentes direitos e privilégios** do que os outros componentes XPC ou o binário principal do aplicativo. EXCETO se um serviço XPC for configurado com [**JoinExistingSession**](https://developer.apple.com/documentation/bundleresources/information\_property\_list/xpcservice/joinexistingsession) definido como “True” no seu arquivo **Info.plist**. Neste caso, o serviço XPC será executado na **mesma sessão de segurança que a aplicação** que o chamou.
|
|
|
|
Os serviços XPC são **iniciados** pelo **launchd** quando necessário e **encerrados** assim que todas as tarefas estão **completas** para liberar recursos do sistema. **Componentes XPC específicos de aplicações só podem ser utilizados pela aplicação**, reduzindo assim o risco associado a potenciais vulnerabilidades.
|
|
|
|
## Serviços XPC de Sistema
|
|
|
|
Serviços XPC de sistema estão acessíveis a todos os usuários. Esses serviços, seja do tipo launchd ou Mach, precisam ser **definidos em arquivos plist** localizados em diretórios especificados como **`/System/Library/LaunchDaemons`**, **`/Library/LaunchDaemons`**, **`/System/Library/LaunchAgents`**, ou **`/Library/LaunchAgents`**.
|
|
|
|
Esses arquivos plist terão uma chave chamada **`MachServices`** com o nome do serviço, e uma chave chamada **`Program`** com o caminho para o binário:
|
|
```xml
|
|
cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>Program</key>
|
|
<string>/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon</string>
|
|
<key>AbandonProcessGroup</key>
|
|
<true/>
|
|
<key>KeepAlive</key>
|
|
<true/>
|
|
<key>Label</key>
|
|
<string>com.jamf.management.daemon</string>
|
|
<key>MachServices</key>
|
|
<dict>
|
|
<key>com.jamf.management.daemon.aad</key>
|
|
<true/>
|
|
<key>com.jamf.management.daemon.agent</key>
|
|
<true/>
|
|
<key>com.jamf.management.daemon.binary</key>
|
|
<true/>
|
|
<key>com.jamf.management.daemon.selfservice</key>
|
|
<true/>
|
|
<key>com.jamf.management.daemon.service</key>
|
|
<true/>
|
|
</dict>
|
|
<key>RunAtLoad</key>
|
|
<true/>
|
|
</dict>
|
|
</plist>
|
|
```
|
|
Os que estão em **`LaunchDameons`** são executados pelo root. Portanto, se um processo não privilegiado puder se comunicar com um deles, ele poderá escalar privilégios.
|
|
|
|
## Mensagens de Eventos XPC
|
|
|
|
Aplicações podem **se inscrever** em diferentes mensagens de eventos, permitindo que sejam **iniciadas sob demanda** quando tais eventos ocorrerem. A **configuração** para esses serviços é feita nos arquivos **plist do launchd**, localizados nos **mesmos diretórios que os anteriores** e contendo uma chave extra **`LaunchEvent`**.
|
|
|
|
### Verificação do Processo de Conexão XPC
|
|
|
|
Quando um processo tenta chamar um método via uma conexão XPC, o **serviço XPC deve verificar se esse processo tem permissão para conectar**. Aqui estão as maneiras comuns de verificar isso e as armadilhas comuns:
|
|
|
|
{% content-ref url="macos-xpc-connecting-process-check/" %}
|
|
[macos-xpc-connecting-process-check](macos-xpc-connecting-process-check/)
|
|
{% endcontent-ref %}
|
|
|
|
## Autorização XPC
|
|
|
|
A Apple também permite que aplicativos **configurem alguns direitos e como obtê-los** para que, se o processo de chamada tiver esses direitos, ele seja **permitido chamar um método** do serviço XPC:
|
|
|
|
{% content-ref url="macos-xpc-authorization.md" %}
|
|
[macos-xpc-authorization.md](macos-xpc-authorization.md)
|
|
{% endcontent-ref %}
|
|
|
|
## Sniffer XPC
|
|
|
|
Para farejar as mensagens XPC, você pode usar [**xpcspy**](https://github.com/hot3eed/xpcspy) que utiliza **Frida**.
|
|
```bash
|
|
# Install
|
|
pip3 install xpcspy
|
|
pip3 install xpcspy --no-deps # To not make xpcspy install Frida 15 and downgrade your Frida installation
|
|
|
|
# Start sniffing
|
|
xpcspy -U -r -W <bundle-id>
|
|
## Using filters (i: for input, o: for output)
|
|
xpcspy -U <prog-name> -t 'i:com.apple.*' -t 'o:com.apple.*' -r
|
|
```
|
|
## Exemplo de Código C para Comunicação XPC
|
|
|
|
{% tabs %}
|
|
{% tab title="xpc_server.c" %}
|
|
```c
|
|
// gcc xpc_server.c -o xpc_server
|
|
|
|
#include <xpc/xpc.h>
|
|
|
|
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;
|
|
}
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="xpc_client.c" %}
|
|
```c
|
|
// gcc xpc_client.c -o xpc_client
|
|
|
|
#include <xpc/xpc.h>
|
|
|
|
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;
|
|
}
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="xyz.hacktricks.service.plist" %}
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
|
|
<dict>
|
|
<key>Label</key>
|
|
<string>xyz.hacktricks.service</string>
|
|
<key>MachServices</key>
|
|
<dict>
|
|
<key>xyz.hacktricks.service</key>
|
|
<true/>
|
|
</dict>
|
|
<key>Program</key>
|
|
<string>/tmp/xpc_server</string>
|
|
<key>ProgramArguments</key>
|
|
<array>
|
|
<string>/tmp/xpc_server</string>
|
|
</array>
|
|
</dict>
|
|
</plist>
|
|
```
|
|
{% 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
|
|
```
|
|
## Exemplo de Código em Objective-C para Comunicação XPC
|
|
|
|
{% tabs %}
|
|
{% tab title="oc_xpc_server.m" %}
|
|
```objectivec
|
|
// gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server
|
|
#include <Foundation/Foundation.h>
|
|
|
|
@protocol MyXPCProtocol
|
|
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
|
|
@end
|
|
|
|
@interface MyXPCObject : NSObject <MyXPCProtocol>
|
|
@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 <NSXPCListenerDelegate>
|
|
@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 <NSXPCListenerDelegate> delegate = [MyDelegate new];
|
|
listener.delegate = delegate;
|
|
[listener resume];
|
|
|
|
sleep(10); // Fake something is done and then it ends
|
|
}
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="oc_xpc_client.m" %}
|
|
```objectivec
|
|
// gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client
|
|
#include <Foundation/Foundation.h>
|
|
|
|
@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;
|
|
}
|
|
```
|
|
{% endtab %}
|
|
|
|
{% tab title="xyz.hacktricks.svcoc.plist" %}
|
|
```xml
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
|
|
<dict>
|
|
<key>Label</key>
|
|
<string>xyz.hacktricks.svcoc</string>
|
|
<key>MachServices</key>
|
|
<dict>
|
|
<key>xyz.hacktricks.svcoc</key>
|
|
<true/>
|
|
</dict>
|
|
<key>Program</key>
|
|
<string>/tmp/oc_xpc_server</string>
|
|
<key>ProgramArguments</key>
|
|
<array>
|
|
<string>/tmp/oc_xpc_server</string>
|
|
</array>
|
|
</dict>
|
|
</plist>
|
|
```
|
|
{% 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
|
|
```
|
|
## Cliente dentro de um código Dylb
|
|
```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 <Foundation/Foundation.h>
|
|
|
|
@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;
|
|
}
|
|
```
|
|
<details>
|
|
|
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
Outras formas de apoiar o HackTricks:
|
|
|
|
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
|
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga**-me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|