<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF**, consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](https://opensea.io/collection/the-peass-family)
* **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez-nous** sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts GitHub.
Les binaires Mac OS sont généralement compilés en tant que **binaires universels**. Un **binaire universel** peut **prendre en charge plusieurs architectures dans le même fichier**.
L'en-tête contient les octets **magic** suivis du **nombre** d'**architectures** contenues dans le fichier (`nfat_arch`) et chaque architecture aura une structure `fat_arch`.
L'en-tête contient des informations de base sur le fichier, telles que les octets magiques pour l'identifier comme un fichier Mach-O et des informations sur l'architecture cible. Vous pouvez le trouver dans : `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"`
Il existe différents types de fichiers, vous pouvez les trouver définis dans le [**code source par exemple ici**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL\_HEADERS/mach-o/loader.h). Les plus importants sont :
*`MH_OBJECT` : Fichier objet relocatable (produits intermédiaires de la compilation, pas encore des exécutables).
La **disposition du fichier en mémoire** est spécifiée ici, détaillant l'emplacement de la **table des symboles**, le contexte du thread principal au démarrage de l'exécution, et les **bibliothèques partagées** requises. Des instructions sont fournies au chargeur dynamique **(dyld)** sur le processus de chargement du binaire en mémoire.
Il existe environ **50 types de commandes de chargement** différents que le système gère différemment. Les plus courants sont : `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB` et `LC_CODE_SIGNATURE`.
Essentiellement, ce type de commande de chargement définit **comment charger les segments \_\_TEXT** (code exécutable) **et \_\_DATA** (données du processus) **selon les décalages indiqués dans la section Data** lorsque le binaire est exécuté.
Il existe **différents types** de segments, tels que le segment **\_\_TEXT**, qui contient le code exécutable d'un programme, et le segment **\_\_DATA**, qui contient les données utilisées par le processus. Ces **segments sont situés dans la section des données** du fichier Mach-O.
**Chaque segment** peut être **divisé en plusieurs sections**. La **structure de la commande de chargement** contient des **informations** sur **ces sections** dans le segment respectif.
Si vous **ajoutez** le **décalage de section** (0x37DC) + le **décalage** où **l'architecture commence**, dans ce cas `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
* **`__PAGEZERO` :** Il indique au noyau de **mapper** l'**adresse zéro** de sorte qu'elle **ne puisse pas être lue, écrite ou exécutée**. Les variables maxprot et minprot dans la structure sont définies à zéro pour indiquer qu'il n'y a **aucun droit de lecture-écriture-exécution sur cette page**.
* Cette allocation est importante pour **atténuer les vulnérabilités de déréférencement de pointeur NULL**. Cela est dû au fait que XNU impose une page zéro stricte qui garantit que la première page (seulement la première) de la mémoire est inaccessible (sauf en i386). Un binaire pourrait satisfaire ces exigences en créant un petit \_\_PAGEZERO (en utilisant `-pagezero_size`) pour couvrir les premiers 4 ko et en ayant le reste de la mémoire 32 bits accessible à la fois en mode utilisateur et en mode noyau.
* **`__TEXT` :** Contient du **code exécutable** avec des autorisations de **lecture** et d'**exécution** (non inscriptible)**.** Sections courantes de ce segment :
* Notez que tout ce contenu est signé mais également marqué comme exécutable (créant plus d'options pour l'exploitation de sections qui n'ont pas nécessairement besoin de ce privilège, comme les sections dédiées aux chaînes).
* **`__DATA_CONST` :** \_\_DATA.\_\_const n'est pas garanti d'être constant (autorisations d'écriture), pas plus que les autres pointeurs et la GOT. Cette section rend `__const`, certains initialiseurs et la table GOT (une fois résolue) **en lecture seule** en utilisant `mprotect`.
* **`__LINKEDIT` :** Contient des informations pour le chargeur (dyld) telles que les entrées de table de symboles, de chaînes et de réadressage. C'est un conteneur générique pour les contenus qui ne sont ni dans `__TEXT` ni dans `__DATA` et son contenu est décrit dans d'autres commandes de chargement.
* Informations dyld : Rebase, opcodes de liaison non paresseux/paresseux/faibles et infos d'exportation
* Début des fonctions : Table des adresses de début des fonctions
* Données dans le code : Îlots de données dans \_\_text
* Table des symboles : Symboles dans le binaire
* Table des symboles indirects : Symboles de pointeur/stub
* Table des chaînes
* Signature de code
* **`__OBJC` :** Contient des informations utilisées par le runtime Objective-C. Bien que ces informations puissent également être trouvées dans le segment \_\_DATA, dans diverses sections \_\_objc\_\*.
* **`__RESTRICT` :** Un segment sans contenu avec une seule section appelée **`__restrict`** (également vide) qui garantit qu'en exécutant le binaire, il ignorera les variables d'environnement DYLD.
Comme il a été possible de le voir dans le code, **les segments prennent également en charge des indicateurs** (bien qu'ils ne soient pas beaucoup utilisés) :
*`SG_PROTECTED_VERSION_1` : Chiffrement. Utilisé par exemple par Finder pour chiffrer le segment de texte `__TEXT`.
### **`LC_UNIXTHREAD/LC_MAIN`**
**`LC_MAIN`** contient le point d'entrée dans l'attribut **entryoff**. Au moment du chargement, **dyld** ajoute simplement cette valeur à la **base du binaire en mémoire**, puis **saute** vers cette instruction pour démarrer l'exécution du code du binaire.
**`LC_UNIXTHREAD`** contient les valeurs que les registres doivent avoir au démarrage du thread principal. Cela a déjà été obsolète mais **`dyld`** l'utilise toujours. Il est possible de voir les valeurs des registres définies par ceci avec :
Contient des informations sur la **signature de code du fichier Mach-O**. Il ne contient qu'un **décalage** qui **pointe** vers le **blob de signature**. Cela se trouve généralement à la toute fin du fichier.\
Cependant, vous pouvez trouver des informations sur cette section dans [**cet article de blog**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) et ce [**gist**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4).
Prise en charge du chiffrement binaire. Cependant, bien sûr, si un attaquant parvient à compromettre le processus, il pourra extraire la mémoire non chiffrée.
Contient le **chemin de l'exécutable du chargeur dynamique** qui mappe les bibliothèques partagées dans l'espace d'adressage du processus. La **valeur est toujours définie sur `/usr/lib/dyld`**. Il est important de noter que sous macOS, le mappage des dylib se fait en **mode utilisateur**, et non en mode noyau.
Obsolète mais lorsqu'il est configuré pour générer des vidages en cas de panique, un vidage de base Mach-O est créé et la version du noyau est définie dans la commande `LC_IDENT`.
UUID aléatoire. Il n'est pas directement utile mais XNU le met en cache avec le reste des informations du processus. Il peut être utilisé dans les rapports de plantage.
Permet d'indiquer des variables d'environnement à dyld avant l'exécution du processus. Cela peut être très dangereux car cela peut permettre d'exécuter du code arbitraire à l'intérieur du processus, donc cette commande de chargement n'est utilisée que dans dyld construit avec `#define SUPPORT_LC_DYLD_ENVIRONMENT` et restreint davantage le traitement uniquement aux variables de la forme `DYLD_..._PATH` spécifiant les chemins de chargement.
Cette commande de chargement décrit une **dépendance de bibliothèque dynamique** qui **indique** au **chargeur** (dyld) de **charger et lier ladite bibliothèque**. Il y a une commande de chargement `LC_LOAD_DYLIB`**pour chaque bibliothèque** requise par le binaire Mach-O.
* Cette commande de chargement est une structure de type **`dylib_command`** (qui contient une structure dylib, décrivant la bibliothèque dynamique dépendante réelle):
Au cœur du fichier se trouve la région des données, composée de plusieurs segments tels que définis dans la région des commandes de chargement. **Une variété de sections de données peut être contenue dans chaque segment**, chaque section **contenant du code ou des données** spécifiques à un type.