From fcce654a8d46ce56a6c8f7ddbb80db846d87802f Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 1 Oct 2025 01:54:13 +0000 Subject: [PATCH] Translated ['src/generic-methodologies-and-resources/basic-forensic-meth --- src/SUMMARY.md | 1 + .../README.md | 7 +- .../mach-o-entitlements-and-ipsw-indexing.md | 213 +++++++++++++ .../universal-binaries-and-mach-o-format.md | 293 +++++++++--------- .../macos-code-signing.md | 125 ++++---- 5 files changed, 434 insertions(+), 205 deletions(-) create mode 100644 src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 27f33cff3..2062b6f9d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -61,6 +61,7 @@ - [Deofuscation vbs (cscript.exe)](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md) - [Discord Cache Forensics](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md) - [Local Cloud Storage](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md) + - [Mach O Entitlements And Ipsw Indexing](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md) - [Office file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md) - [PDF File analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md) - [PNG tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md) diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md index ab6c015cf..002f33b44 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md @@ -1,4 +1,4 @@ -# Astuces pour logiciels/types de fichiers spécifiques +# Astuces spécifiques pour logiciels/types de fichiers {{#include ../../../banners/hacktricks-training.md}} @@ -54,4 +54,9 @@ video-and-audio-file-analysis.md zips-tricks.md {{#endref}} + +{{#ref}} +mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md new file mode 100644 index 000000000..a44f8f34c --- /dev/null +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md @@ -0,0 +1,213 @@ +# Extraction des entitlements Mach-O & indexation d'IPSW + +{{#include ../../../banners/hacktricks-training.md}} + +## Vue d'ensemble + +Cette page explique comment extraire les entitlements depuis des binaires Mach-O de façon programmatique en parcourant LC_CODE_SIGNATURE et en analysant le code signing SuperBlob, et comment mettre cela à l'échelle sur les firmwares IPSW d'Apple en montant et en indexant leur contenu pour des recherches/diffs forensiques. + +Si vous avez besoin d'un rappel sur le format Mach-O et le code signing, voir aussi : macOS code signing and SuperBlob internals. +- Consultez macOS code signing details (SuperBlob, Code Directory, special slots): [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md) +- Consultez general Mach-O structures/load commands: [Universal binaries & Mach-O Format](../../../macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md) + + +## Entitlements dans Mach-O : où elles se trouvent + +Les entitlements sont stockés dans les données de code signature référencées par le load command LC_CODE_SIGNATURE et placées dans le segment __LINKEDIT. La signature est un CS_SuperBlob contenant plusieurs blobs (code directory, requirements, entitlements, CMS, etc.). Le blob d'entitlements est un CS_GenericBlob dont les données sont un Apple Binary Property List (bplist00) associant des clés d'entitlement à des valeurs. + +Key structures (from xnu): +```c +/* mach-o/loader.h */ +struct mach_header_64 { +uint32_t magic; +cpu_type_t cputype; +cpu_subtype_t cpusubtype; +uint32_t filetype; +uint32_t ncmds; +uint32_t sizeofcmds; +uint32_t flags; +uint32_t reserved; +}; + +struct load_command { +uint32_t cmd; +uint32_t cmdsize; +}; + +/* Entitlements live behind LC_CODE_SIGNATURE (cmd=0x1d) */ +struct linkedit_data_command { +uint32_t cmd; /* LC_CODE_SIGNATURE */ +uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ +uint32_t dataoff; /* file offset of data in __LINKEDIT */ +uint32_t datasize; /* file size of data in __LINKEDIT */ +}; + +/* osfmk/kern/cs_blobs.h */ +typedef struct __SC_SuperBlob { +uint32_t magic; /* CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 */ +uint32_t length; +uint32_t count; +CS_BlobIndex index[]; +} CS_SuperBlob; + +typedef struct __BlobIndex { +uint32_t type; /* e.g., CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 */ +uint32_t offset; /* offset of entry */ +} CS_BlobIndex; + +typedef struct __SC_GenericBlob { +uint32_t magic; /* same as type when standalone */ +uint32_t length; +char data[]; /* Apple Binary Plist containing entitlements */ +} CS_GenericBlob; +``` +Constantes importantes : +- LC_CODE_SIGNATURE cmd = 0x1d +- CS SuperBlob magic = 0xfade0cc0 +- Entitlements blob type (CSMAGIC_EMBEDDED_ENTITLEMENTS) = 0xfade7171 +- DER entitlements may be present via special slot (e.g., -7), see the macOS Code Signing page for special slots and DER entitlements notes + +Remarque : les binaires multi-arch (fat) contiennent plusieurs slices Mach-O. Vous devez choisir la slice correspondant à l'architecture que vous souhaitez inspecter, puis parcourir ses load commands. + + +## Étapes d'extraction (génériques, suffisamment sans perte) + +1) Parser le Mach-O header ; itérer ncmds records de load_command. +2) Localiser LC_CODE_SIGNATURE ; lire linkedit_data_command.dataoff/datasize pour mapper le Code Signing SuperBlob placé dans __LINKEDIT. +3) Valider CS_SuperBlob.magic == 0xfade0cc0 ; itérer count entries de CS_BlobIndex. +4) Localiser index.type == 0xfade7171 (embedded entitlements). Lire le CS_GenericBlob pointé et parser ses données comme un Apple binary plist (bplist00) pour obtenir les entitlements en clé/valeur. + +Notes d'implémentation : +- Les structures de code signature utilisent des champs big-endian ; inverser l'ordre des octets lors du parsing sur des hosts little-endian. +- Les données du GenericBlob des entitlements sont elles-mêmes un binary plist (pris en charge par les bibliothèques plist standard). +- Certains binaires iOS peuvent porter des DER entitlements ; certains stores/slots diffèrent aussi entre plateformes/versions. Vérifier à la fois les entitlements standard et DER selon les besoins. +- Pour les fat binaries, utiliser les fat headers (FAT_MAGIC/FAT_MAGIC_64) pour localiser la slice et l'offset corrects avant de parcourir les load commands du Mach-O. + + +## Plan d'analyse minimal (Python) + +The following is a compact outline showing the control flow to find and decode entitlements. It intentionally omits robust bounds checks and full fat binary support for brevity. +```python +import plistlib, struct + +LC_CODE_SIGNATURE = 0x1d +CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 +CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 + +# all code-signing integers are big-endian per cs_blobs.h +be32 = lambda b, off: struct.unpack_from(">I", b, off)[0] + +def parse_entitlements(macho_bytes): +# assume already positioned at a single-arch Mach-O slice +magic, = struct.unpack_from(" +``` +- Parcourir les volumes montés pour localiser les fichiers Mach-O (vérifier le magic et/ou utiliser file/otool), puis analyser les entitlements et les frameworks importés. +- Conserver une vue normalisée dans une base de données relationnelle pour éviter une croissance linéaire à travers des milliers d'IPSWs : +- executables, operating_system_versions, entitlements, frameworks +- many-to-many: executable↔OS version, executable↔entitlement, executable↔framework + +Exemple de requête pour lister toutes les versions d'OS contenant un nom d'exécutable donné : +```sql +SELECT osv.version AS "Versions" +FROM device d +LEFT JOIN operating_system_version osv ON osv.device_id = d.id +LEFT JOIN executable_operating_system_version eosv ON eosv.operating_system_version_id = osv.id +LEFT JOIN executable e ON e.id = eosv.executable_id +WHERE e.name = "launchd"; +``` +Notes sur la portabilité de la DB (si vous implémentez votre propre indexeur) : +- Utilisez un ORM/une abstraction (par ex., SeaORM) pour garder le code agnostique vis-à-vis de la DB (SQLite/PostgreSQL). +- SQLite n'exige AUTOINCREMENT que pour un INTEGER PRIMARY KEY ; si vous voulez des PK i64 en Rust, générez les entités en i32 et convertissez les types, SQLite stocke INTEGER comme un entier signé sur 8 octets en interne. + + +## Outils open-source et références pour entitlement hunting + +- Firmware mount/download: https://github.com/blacktop/ipsw +- Bases de données et références d'entitlements : +- Entitlement DB de Jonathan Levin: https://newosxbook.com/ent.php +- entdb: https://github.com/ChiChou/entdb +- Indexeur à grande échelle (Rust, Web UI auto-hébergée + OpenAPI): https://github.com/synacktiv/appledb_rs +- Apple headers pour structures et constantes : +- loader.h (Mach-O headers, load commands) +- cs_blobs.h (SuperBlob, GenericBlob, CodeDirectory) + +Pour plus d'informations sur les internals du code signing (Code Directory, special slots, DER entitlements), voir : [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md) + + +## Références + +- [appledb_rs: a research support tool for Apple platforms](https://www.synacktiv.com/publications/appledbrs-un-outil-daide-a-la-recherche-sur-plateformes-apple.html) +- [synacktiv/appledb_rs](https://github.com/synacktiv/appledb_rs) +- [blacktop/ipsw](https://github.com/blacktop/ipsw) +- [Jonathan Levin’s entitlement DB](https://newosxbook.com/ent.php) +- [ChiChou/entdb](https://github.com/ChiChou/entdb) +- [XNU cs_blobs.h](https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/cs_blobs.h) +- [XNU mach-o/loader.h](https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h) +- [SQLite Datatypes](https://sqlite.org/datatype3.html) + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md index 3bf278406..bbf14556a 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md @@ -4,45 +4,45 @@ ## Informations de base -Les binaires Mac OS sont généralement compilés en tant que **binaires universels**. Un **binaire universel** peut **supporter plusieurs architectures dans le même fichier**. +Mac OS binaries usually are compiled as **universal binaries**. A **universal binary** can **support multiple architectures in the same file**. -Ces binaires suivent la **structure Mach-O** qui est essentiellement composée de : +These binaries follows the **Mach-O structure** which is basically compased of: - En-tête -- Commandes de chargement +- Load Commands - Données ![https://alexdremov.me/content/images/2022/10/6XLCD.gif](<../../../images/image (470).png>) -## En-tête Fat +## Fat Header -Recherchez le fichier avec : `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"` +Cherchez le fichier avec : `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"`
#define FAT_MAGIC	0xcafebabe
 #define FAT_CIGAM	0xbebafeca	/* NXSwapLong(FAT_MAGIC) */
 
 struct fat_header {
-	uint32_t	magic;		/* FAT_MAGIC ou FAT_MAGIC_64 */
-	uint32_t	nfat_arch;	/* nombre de structures qui suivent */
+	uint32_t	magic;		/* FAT_MAGIC or FAT_MAGIC_64 */
+	uint32_t	nfat_arch;	/* number of structs that follow */
 };
 
 struct fat_arch {
-cpu_type_t	cputype;	/* spécificateur de cpu (int) */
-cpu_subtype_t	cpusubtype;	/* spécificateur de machine (int) */
-uint32_t	offset;		/* décalage de fichier vers ce fichier objet */
-uint32_t	size;		/* taille de ce fichier objet */
-uint32_t	align;		/* alignement comme une puissance de 2 */
+cpu_type_t	cputype;	/* cpu specifier (int) */
+cpu_subtype_t	cpusubtype;	/* machine specifier (int) */
+uint32_t	offset;		/* file offset to this object file */
+uint32_t	size;		/* size of this object file */
+uint32_t	align;		/* alignment as a power of 2 */
 };
 
-L'en-tête contient les **octets magiques** suivis du **nombre** d'**archs** que le fichier **contient** (`nfat_arch`) et chaque arch aura une structure `fat_arch`. +L'en-tête contient les octets **magic** suivis du **nombre** d'**archs** que le fichier **contient** (`nfat_arch`) et chaque arch aura une `fat_arch` struct. Vérifiez-le avec :
% file /bin/ls
 /bin/ls: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
-/bin/ls (pour l'architecture x86_64):	Mach-O 64-bit executable x86_64
-/bin/ls (pour l'architecture arm64e):	Mach-O 64-bit executable arm64e
+/bin/ls (for architecture x86_64):	Mach-O 64-bit executable x86_64
+/bin/ls (for architecture arm64e):	Mach-O 64-bit executable arm64e
 
 % otool -f -v /bin/ls
 Fat headers
@@ -64,15 +64,15 @@ capabilities PTR_AUTH_VERSION USERSPACE 0
     align 2^14 (16384)
 
-ou en utilisant l'outil [Mach-O View](https://sourceforge.net/projects/machoview/) : +or using the [Mach-O View](https://sourceforge.net/projects/machoview/) tool:
-Comme vous pouvez le penser, un binaire universel compilé pour 2 architectures **double la taille** de celui compilé pour une seule arch. +Comme vous pouvez l'imaginer, un universal binary compilé pour 2 architectures **double généralement la taille** de celui compilé pour une seule arch. -## **En-tête Mach-O** +## **Mach-O Header** -L'en-tête contient des informations de base sur le fichier, telles que des 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$"` +L'en-tête contient des informations de base sur le fichier, comme les octets magic permettant de l'identifier en tant que 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$"` ```c #define MH_MAGIC 0xfeedface /* the mach magic number */ #define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ @@ -101,18 +101,18 @@ uint32_t reserved; /* reserved */ ``` ### Types de fichiers Mach-O -Il existe différents types de fichiers, que vous pouvez 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 : +Il existe différents types de fichiers, vous pouvez les trouver définis dans la [**source code for example here**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h). Les plus importants sont : -- `MH_OBJECT` : Fichier objet rélocalisable (produits intermédiaires de la compilation, pas encore exécutables). -- `MH_EXECUTE` : Fichiers exécutables. -- `MH_FVMLIB` : Fichier de bibliothèque VM fixe. -- `MH_CORE` : Dumps de code -- `MH_PRELOAD` : Fichier exécutable préchargé (plus supporté dans XNU) -- `MH_DYLIB` : Bibliothèques dynamiques -- `MH_DYLINKER` : Linker dynamique -- `MH_BUNDLE` : "Fichiers de plugin". Générés en utilisant -bundle dans gcc et chargés explicitement par `NSBundle` ou `dlopen`. -- `MH_DYSM` : Fichier compagnon `.dSym` (fichier avec des symboles pour le débogage). -- `MH_KEXT_BUNDLE` : Extensions du noyau. +- `MH_OBJECT`: Fichier objet relocatable (produits intermédiaires de compilation, pas encore exécutables). +- `MH_EXECUTE`: Fichiers exécutables. +- `MH_FVMLIB`: Fichier de bibliothèque VM fixe. +- `MH_CORE`: Dumps de code +- `MH_PRELOAD`: Fichier exécutable préchargé (n'est plus supporté dans XNU) +- `MH_DYLIB`: Bibliothèques dynamiques +- `MH_DYLINKER`: Linker dynamique +- `MH_BUNDLE`: "Plugin files". Générés en utilisant -bundle dans gcc et chargés explicitement par `NSBundle` ou `dlopen`. +- `MH_DYSM`: Fichier compagnon `.dSym` (fichier contenant des symboles pour le débogage). +- `MH_KEXT_BUNDLE`: Extensions du noyau. ```bash # Checking the mac header of a binary otool -arch arm64e -hv /bin/ls @@ -120,67 +120,67 @@ Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DYLDLINK TWOLEVEL PIE ``` -Ou en utilisant [Mach-O View](https://sourceforge.net/projects/machoview/) : +Ou en utilisant [Mach-O View](https://sourceforge.net/projects/machoview/):
-## **Drapeaux Mach-O** +## **Mach-O Flags** -Le code source définit également plusieurs drapeaux utiles pour le chargement des bibliothèques : +Le code source définit également plusieurs flags utiles pour le chargement des bibliothèques : -- `MH_NOUNDEFS` : Pas de références non définies (entièrement lié) -- `MH_DYLDLINK` : Liaison Dyld -- `MH_PREBOUND` : Références dynamiques préliées. -- `MH_SPLIT_SEGS` : Le fichier divise les segments r/o et r/w. -- `MH_WEAK_DEFINES` : Le binaire a des symboles définis faibles -- `MH_BINDS_TO_WEAK` : Le binaire utilise des symboles faibles -- `MH_ALLOW_STACK_EXECUTION` : Rendre la pile exécutable -- `MH_NO_REEXPORTED_DYLIBS` : Bibliothèque sans commandes LC_REEXPORT -- `MH_PIE` : Exécutable indépendant de la position -- `MH_HAS_TLV_DESCRIPTORS` : Il y a une section avec des variables locales au thread -- `MH_NO_HEAP_EXECUTION` : Pas d'exécution pour les pages heap/données -- `MH_HAS_OBJC` : Le binaire a des sections oBject-C -- `MH_SIM_SUPPORT` : Support du simulateur -- `MH_DYLIB_IN_CACHE` : Utilisé sur les dylibs/frameworks dans le cache de bibliothèques partagées. +- `MH_NOUNDEFS`: Pas de références non définies (entièrement lié) +- `MH_DYLDLINK`: Liaison dyld +- `MH_PREBOUND`: Références dynamiques préliées. +- `MH_SPLIT_SEGS`: Sépare les segments r/o et r/w. +- `MH_WEAK_DEFINES`: Le binaire possède des symboles définis faibles +- `MH_BINDS_TO_WEAK`: Le binaire utilise des symboles faibles +- `MH_ALLOW_STACK_EXECUTION`: Rendre la pile exécutable +- `MH_NO_REEXPORTED_DYLIBS`: Bibliothèque sans commandes LC_REEXPORT +- `MH_PIE`: Exécutable indépendant de la position +- `MH_HAS_TLV_DESCRIPTORS`: Il y a une section avec des variables thread-local +- `MH_NO_HEAP_EXECUTION`: Pas d'exécution pour les pages heap/data +- `MH_HAS_OBJC`: Le binaire contient des sections Objective-C +- `MH_SIM_SUPPORT`: Support du simulateur +- `MH_DYLIB_IN_CACHE`: Utilisé pour les dylibs/frameworks dans le cache de librairies partagées. -## **Commandes de chargement Mach-O** +## **Mach-O Load commands** -La **disposition du fichier en mémoire** est spécifiée ici, détaillant la **localisation de la table des symboles**, le contexte du thread principal au début 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. +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 utilise la structure **load_command**, définie dans le **`loader.h`** mentionné : +Il utilise la structure **load_command**, définie dans le fichier **`loader.h`** mentionné : ```objectivec struct load_command { uint32_t cmd; /* type of load command */ uint32_t cmdsize; /* total size of command in bytes */ }; ``` -Il y a environ **50 types différents de commandes de chargement** 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`. +Il existe environ **50 types différents de commandes de chargement** que le système gère différemment. Les plus courantes sont : `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB`, et `LC_CODE_SIGNATURE`. ### **LC_SEGMENT/LC_SEGMENT_64** > [!TIP] -> Fondamentalement, ce type de commande de chargement définit **comment charger le \_\_TEXT** (code exécutable) **et le \_\_DATA** (données pour le processus) **segments** selon les **offsets indiqués dans la section de données** lorsque le binaire est exécuté. +> En gros, ce type de commande de chargement définit **comment charger le \_\_TEXT** (code exécutable) **et le \_\_DATA** (données pour le processus) **segments** selon les **offsets indiqués dans la section Data** lorsque le binaire est exécuté. Ces commandes **définissent des segments** qui sont **mappés** dans l'**espace mémoire virtuel** d'un processus lorsqu'il 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 des données utilisées par le processus. Ces **segments se trouvent dans la section de données** du fichier Mach-O. +Il existe **différents types** de segments, comme 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 se trouvent dans la section de données** du fichier Mach-O. -**Chaque segment** peut être **divisé** en plusieurs **sections**. La **structure de commande de chargement** contient **des informations** sur **ces sections** dans le segment respectif. +**Chaque segment** peut être en outre **divisé** en plusieurs **sections**. La **structure de la commande de chargement** contient des **informations** sur **ces sections** au sein du segment concerné. -Dans l'en-tête, vous trouvez d'abord l'**en-tête de segment** : +Dans l'en-tête, on trouve d'abord l'**en-tête de segment** : -
struct segment_command_64 { /* pour les architectures 64 bits */
+
struct segment_command_64 { /* for 64-bit architectures */
 uint32_t	cmd;		/* LC_SEGMENT_64 */
-uint32_t	cmdsize;	/* inclut sizeof section_64 structs */
-char		segname[16];	/* nom du segment */
-uint64_t	vmaddr;		/* adresse mémoire de ce segment */
-uint64_t	vmsize;		/* taille mémoire de ce segment */
-uint64_t	fileoff;	/* décalage de fichier de ce segment */
-uint64_t	filesize;	/* quantité à mapper depuis le fichier */
-int32_t		maxprot;	/* protection VM maximale */
-int32_t		initprot;	/* protection VM initiale */
-	uint32_t	nsects;		/* nombre de sections dans le segment */
-	uint32_t	flags;		/* drapeaux */
+uint32_t	cmdsize;	/* includes sizeof section_64 structs */
+char		segname[16];	/* segment name */
+uint64_t	vmaddr;		/* memory address of this segment */
+uint64_t	vmsize;		/* memory size of this segment */
+uint64_t	fileoff;	/* file offset of this segment */
+uint64_t	filesize;	/* amount to map from the file */
+int32_t		maxprot;	/* maximum VM protection */
+int32_t		initprot;	/* initial VM protection */
+	uint32_t	nsects;		/* number of sections in segment */
+	uint32_t	flags;		/* flags */
 };
 
@@ -205,62 +205,62 @@ uint32_t reserved2; /* reserved (for count or sizeof) */ uint32_t reserved3; /* reserved */ }; ``` -Exemple de **titre de section** : +Exemple d'**en-tête de section** :
-Si vous **ajoutez** le **décalage de section** (0x37DC) + le **décalage** où le **arch commence**, dans ce cas `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC` +Si vous **ajoutez** l'**offset de section** (0x37DC) + l'**offset** où **arch** commence, dans ce cas `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
-Il est également possible d'obtenir des **informations sur les en-têtes** depuis la **ligne de commande** avec : +Il est également possible d'obtenir les **informations des headers** depuis la **ligne de commande** avec : ```bash otool -lv /bin/ls ``` -Segments communs chargés par cette commande : +Common segments loaded by this cmd: -- **`__PAGEZERO` :** Il indique au noyau de **mapper** l'**adresse zéro** afin 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**. En effet, 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 4k et en rendant 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 permissions de **lecture** et **d'exécution** (pas d'écriture)**.** Sections communes de ce segment : -- `__text` : Code binaire compilé -- `__const` : Données constantes (lecture seule) -- `__[c/u/os_log]string` : Constantes de chaînes C, Unicode ou os logs -- `__stubs` et `__stubs_helper` : Impliqués lors du processus de chargement de la bibliothèque dynamique -- `__unwind_info` : Données de dépliage de pile. -- 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` :** Contient des données qui sont **lisibles** et **écrites** (pas exécutables)**.** -- `__got:` Table d'offset global -- `__nl_symbol_ptr` : Pointeur de symbole non paresseux (liaison au chargement) -- `__la_symbol_ptr` : Pointeur de symbole paresseux (liaison à l'utilisation) -- `__const` : Devrait être des données en lecture seule (pas vraiment) -- `__cfstring` : Chaînes CoreFoundation -- `__data` : Variables globales (qui ont été initialisées) -- `__bss` : Variables statiques (qui n'ont pas été initialisées) -- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc) : Informations utilisées par le runtime Objective-C -- **`__DATA_CONST` :** \_\_DATA.\_\_const n'est pas garanti d'être constant (permissions d'écriture), ni d'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 linker (dyld) telles que, symboles, chaînes et entrées de table de relocation. C'est un conteneur générique pour des 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/faible et informations d'exportation -- Début des fonctions : Table des adresses de début des fonctions -- Données dans le code : Îles de données dans \_\_text -- Table des symboles : Symboles dans le binaire -- Table des symboles indirects : Symboles 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, au sein de diverses sections \_\_objc\_\*. -- **`__RESTRICT` :** Un segment sans contenu avec une seule section appelée **`__restrict`** (également vide) qui garantit que lors de l'exécution du binaire, il ignorera les variables d'environnement DYLD. +- **`__PAGEZERO`:** Il indique au noyau de **mapper** l'**adresse zéro** afin qu'elle **ne puisse pas être lue, écrite ou exécutée**. Les variables maxprot et minprot de la structure sont réglées à zéro pour indiquer qu'il n'y a **aucun droit 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**. En effet, XNU applique une page zéro stricte qui garantit que la première page (seule la première) de la mémoire est inaccessible (sauf sur i386). Un binaire peut satisfaire cette exigence en construisant un petit \_\_PAGEZERO (en utilisant le `-pagezero_size`) pour couvrir les premiers 4k et en rendant le reste de la mémoire 32bit accessible en mode utilisateur et noyau. +- **`__TEXT`**: Contient du **code** **exécutable** avec les permissions **lecture** et **exécution** (pas d'écriture)**.** Sections communes de ce segment : +- `__text`: Code binaire compilé +- `__const`: Données constantes (lecture seule) +- `__[c/u/os_log]string`: Constantes de chaînes C, Unicode ou os logs +- `__stubs` et `__stubs_helper`: Impliqués lors du chargement des bibliothèques dynamiques +- `__unwind_info`: Données d'unwind de pile. +- Notez que tout ce contenu est signé mais aussi marqué comme exécutable (offrant davantage 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`**: Contient des données **lisibles** et **écrivables** (pas exécutables)**.** +- `__got:` Global Offset Table +- `__nl_symbol_ptr`: Pointeur de symbole non-lazy (liaison au chargement) +- `__la_symbol_ptr`: Pointeur de symbole lazy (liaison à l'utilisation) +- `__const`: Devrait être des données en lecture seule (pas vraiment) +- `__cfstring`: Chaînes CoreFoundation +- `__data`: Variables globales (initialisées) +- `__bss`: Variables statiques (non initialisées) +- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc): Informations utilisées par le runtime Objective-C +- **`__DATA_CONST`**: \_\_DATA.\_\_const n'est pas garanti constant (permissions d'écriture), ni le reste des pointeurs et la GOT. Cette section rend `__const`, certains initialisateurs et la table GOT (une fois résolue) **en lecture seule** en utilisant `mprotect`. +- **`__LINKEDIT`**: Contient des informations pour le linker (dyld) telles que les tables de symboles, de chaînes et de relocalisation. C'est un conteneur générique pour le contenu qui n'est ni dans `__TEXT` ni dans `__DATA` et son contenu est décrit dans d'autres load commands. +- dyld information: Rebase, opcodes de liaison Non-lazy/lazy/weak et info d'export +- Functions starts: Table of start addresses of functions +- Data In Code: îlots de données dans \_\_text +- SYmbol Table: Table des symboles dans le binaire +- Indirect Symbol Table: Pointeurs/symboles de stub +- String Table +- Code Signature +- **`__OBJC`**: Contient des informations utilisées par le runtime Objective-C. Bien que ces informations puissent aussi se trouver dans le segment \_\_DATA, au sein des différentes sections \_\_objc\_\*. +- **`__RESTRICT`**: Un segment sans contenu avec une seule section appelée **`__restrict`** (aussi vide) qui assure que, lors de l'exécution du binaire, les variables d'environnement DYLD seront ignorées. -Comme il a été possible de le voir dans le code, **les segments prennent également en charge des drapeaux** (bien qu'ils ne soient pas très utilisés) : +As it was possible to see in the code, **segments also support flags** (although they aren't used very much): -- `SG_HIGHVM` : Core uniquement (non utilisé) -- `SG_FVMLIB` : Non utilisé -- `SG_NORELOC` : Le segment n'a pas de relocation -- `SG_PROTECTED_VERSION_1` : Chiffrement. Utilisé par exemple par Finder pour chiffrer le segment `__TEXT`. +- `SG_HIGHVM`: Core only (not used) +- `SG_FVMLIB`: Not used +- `SG_NORELOC`: Segment has no relocation +- `SG_PROTECTED_VERSION_1`: Encryption. Used for example by Finder to encrypt text `__TEXT` segment. ### **`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** à cette instruction pour commencer l'exécution du code du binaire. +**`LC_MAIN`** contient le point d'entrée dans l'attribut **entryoff.** Au moment du chargement, **dyld** ajoute simplement cette valeur à la base (en mémoire) du binaire, puis **saute** à cette instruction pour démarrer l'exécution du code du binaire. -**`LC_UNIXTHREAD`** contient les valeurs que les registres doivent avoir lors du démarrage du thread principal. Cela a déjà été déprécié mais **`dyld`** l'utilise toujours. Il est possible de voir les valeurs des registres définies par cela avec : +**`LC_UNIXTHREAD`** contient les valeurs que doivent avoir les registres lors du démarrage du thread principal. Ceci est déjà déprécié mais **`dyld`** l'utilise encore. Il est possible de voir les valeurs des registres définies par ceci avec : ```bash otool -l /usr/lib/dyld [...] @@ -286,34 +286,39 @@ cpsr 0x00000000 ``` ### **`LC_CODE_SIGNATURE`** -Contient des informations sur la **signature de code du fichier Macho-O**. Il ne contient qu'un **offset** 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 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4). +{{#ref}} +../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + + +Contient des informations sur la **signature de code du fichier Mach-O**. Il contient seulement un **offset** qui **pointe** vers le **blob de signature**. Ceci se trouve typiquement à la toute fin du fichier.\ +Cependant, vous pouvez trouver des informations sur cette section dans [**this blog post**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) et ce [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4). ### **`LC_ENCRYPTION_INFO[_64]`** -Support pour le chiffrement binaire. Cependant, bien sûr, si un attaquant parvient à compromettre le processus, il pourra vider la mémoire sans chiffrement. +Prend en charge le chiffrement binaire. Cependant, bien sûr, si un attaquant parvient à compromettre le processus, il pourra extraire la mémoire en clair. ### **`LC_LOAD_DYLINKER`** -Contient le **chemin vers 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 dans macOS, le mappage de dylib se fait en **mode utilisateur**, et non en mode noyau. +Contient le **chemin vers l'exécutable du dynamic linker** qui mappe les bibliothèques partagées dans l'espace d'adresses du processus. La **valeur est toujours définie sur `/usr/lib/dyld`**. Il est important de noter que sous macOS, le mapping des dylib se fait en **mode utilisateur**, pas en mode noyau. ### **`LC_IDENT`** -Obsolète mais lorsqu'il est configuré pour générer des dumps en cas de panique, un dump de cœur Mach-O est créé et la version du noyau est définie dans la commande `LC_IDENT`. +Obsolète, mais lorsqu'il est configuré pour générer des dumps lors d'un panic, un core dump Mach-O est créé et la version du kernel est définie dans la commande `LC_IDENT`. ### **`LC_UUID`** -UUID aléatoire. Il est utile pour tout directement mais XNU le met en cache avec le reste des informations sur le processus. Il peut être utilisé dans les rapports de crash. +UUID aléatoire. Il n'est pas utile directement pour grand-chose mais XNU le met en cache avec le reste des infos du processus. Il peut être utilisé dans les rapports de crash. ### **`LC_DYLD_ENVIRONMENT`** -Permet d'indiquer des variables d'environnement au dyld avant que le processus ne soit exécuté. 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 les builds de dyld 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. +Permet d'indiquer des variables d'environnement à dyld avant que le processus ne soit exécuté. Cela peut être très dangereux car cela peut permettre d'exécuter du code arbitraire dans le processus, donc cette load command n'est utilisée que dans les build de dyld avec `#define SUPPORT_LC_DYLD_ENVIRONMENT` et restreint en outre le traitement uniquement aux variables de la forme `DYLD_..._PATH` spécifiant des chemins de chargement. ### **`LC_LOAD_DYLIB`** -Cette commande de chargement décrit une dépendance de **bibliothèque** **dynamique** qui **informe** le **chargeur** (dyld) de **charger et lier ladite bibliothèque**. Il y a une commande de chargement `LC_LOAD_DYLIB` **pour chaque bibliothèque** dont le binaire Mach-O a besoin. +Cette load command décrit une dépendance de **bibliothèque dynamique** qui **indique** au **loader** (dyld) de **charger et lier ladite bibliothèque**. Il y a une `LC_LOAD_DYLIB` load command **pour chaque bibliothèque** dont le binaire Mach-O a besoin. -- Cette commande de chargement est une structure de type **`dylib_command`** (qui contient une struct dylib, décrivant la bibliothèque dynamique dépendante réelle) : +- This load command is a structure of type **`dylib_command`** (which contains a struct dylib, describing the actual dependent dynamic library): ```objectivec struct dylib_command { uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */ @@ -330,7 +335,7 @@ uint32_t compatibility_version; /* library's compatibility vers number*/ ``` ![](<../../../images/image (486).png>) -Vous pouvez également obtenir ces informations depuis le cli avec : +Vous pouvez aussi obtenir ces informations depuis la CLI avec : ```bash otool -L /bin/ls /bin/ls: @@ -338,55 +343,55 @@ otool -L /bin/ls /usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0) ``` -Certaines bibliothèques potentielles liées aux logiciels malveillants sont : +Quelques bibliothèques potentiellement liées aux malwares sont : -- **DiskArbitration** : Surveillance des clés USB -- **AVFoundation :** Capture audio et vidéo -- **CoreWLAN** : Scans Wifi. - -> [!NOTE] -> Un binaire Mach-O peut contenir un ou **plusieurs** **constructeurs**, qui seront **exécutés** **avant** l'adresse spécifiée dans **LC_MAIN**.\ -> Les décalages de tous les constructeurs sont conservés dans la section **\_\_mod_init_func** du segment **\_\_DATA_CONST**. - -## **Données Mach-O** - -Au cœur du fichier se trouve la région de données, qui est composée de plusieurs segments comme défini dans la région des commandes de chargement. **Une variété de sections de données peut être contenue dans chaque segment**, chaque section **détenant du code ou des données** spécifiques à un type. +- **DiskArbitration**: Surveillance des périphériques USB +- **AVFoundation:** Capture audio et vidéo +- **CoreWLAN**: Analyses Wi‑Fi > [!TIP] -> Les données sont essentiellement la partie contenant toutes les **informations** qui sont chargées par les commandes de chargement **LC_SEGMENTS_64** +> Un binaire Mach-O peut contenir un ou **plusieurs** **constructeurs**, qui seront **exécutés** **avant** l'adresse spécifiée dans **LC_MAIN**.\ +> Les offsets de ces constructeurs sont stockés dans la section **\_\_mod_init_func** du segment **\_\_DATA_CONST**. + +## **Mach-O Data** + +Au cœur du fichier se trouve la région de données, qui est composée de plusieurs segments tels que définis dans la région des load-commands. **Une variété de sections de données peut être hébergée dans chaque segment**, chaque section **contenant du code ou des données** spécifiques à un type. + +> [!TIP] +> Les données sont essentiellement la partie contenant toutes les **informations** qui sont chargées par les load commands **LC_SEGMENTS_64** ![https://www.oreilly.com/api/v2/epubs/9781785883378/files/graphics/B05055_02_38.jpg](<../../../images/image (507) (3).png>) Cela inclut : -- **Table des fonctions :** Qui contient des informations sur les fonctions du programme. -- **Table des symboles** : Qui contient des informations sur les fonctions externes utilisées par le binaire -- Elle pourrait également contenir des fonctions internes, des noms de variables ainsi que d'autres. +- **Function table:** Qui contient des informations sur les fonctions du programme. +- **Symbol table**: Qui contient des informations sur les fonctions externes utilisées par le binaire +- Il peut aussi contenir des fonctions internes, des noms de variables et plus encore. -Pour le vérifier, vous pourriez utiliser l'outil [**Mach-O View**](https://sourceforge.net/projects/machoview/) : +Pour le vérifier, vous pouvez utiliser l'outil [**Mach-O View**](https://sourceforge.net/projects/machoview/) :
-Ou depuis le cli : +Ou depuis le cli: ```bash size -m /bin/ls ``` -## Sections communes d'Objective-C +## Objetive-C Sections communes Dans le segment `__TEXT` (r-x) : -- `__objc_classname` : Noms de classes (chaînes) -- `__objc_methname` : Noms de méthodes (chaînes) -- `__objc_methtype` : Types de méthodes (chaînes) +- `__objc_classname`: Noms de classes (chaînes) +- `__objc_methname`: Noms de méthodes (chaînes) +- `__objc_methtype`: Types de méthodes (chaînes) Dans le segment `__DATA` (rw-) : -- `__objc_classlist` : Pointeurs vers toutes les classes Objective-C -- `__objc_nlclslist` : Pointeurs vers les classes Objective-C non paresseuses -- `__objc_catlist` : Pointeur vers les catégories -- `__objc_nlcatlist` : Pointeur vers les catégories non paresseuses -- `__objc_protolist` : Liste des protocoles -- `__objc_const` : Données constantes +- `__objc_classlist`: Pointeurs vers toutes les classes Objetive-C +- `__objc_nlclslist`: Pointeurs vers les classes Objective-C Non-Lazy +- `__objc_catlist`: Pointeur vers les catégories +- `__objc_nlcatlist`: Pointeur vers les catégories Non-Lazy +- `__objc_protolist`: Liste des protocoles +- `__objc_const`: Données constantes - `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`... ## Swift diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md index ce62ae819..707c82d8f 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md @@ -4,12 +4,17 @@ ## Informations de base -Les binaires Mach-o contiennent une commande de chargement appelée **`LC_CODE_SIGNATURE`** qui indique le **décalage** et la **taille** des signatures à l'intérieur du binaire. En fait, en utilisant l'outil GUI MachOView, il est possible de trouver à la fin du binaire une section appelée **Code Signature** avec ces informations : +{{#ref}} +../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + + +Les binaires Mach-o contiennent une commande de chargement appelée **`LC_CODE_SIGNATURE`** qui indique le **décalage** et la **taille** des signatures à l'intérieur du binaire. En fait, en utilisant l'outil GUI MachOView, il est possible de trouver, à la fin du binaire, une section appelée **Code Signature** avec ces informations :
-L'en-tête magique de la Code Signature est **`0xFADE0CC0`**. Ensuite, vous avez des informations telles que la longueur et le nombre de blobs du superBlob qui les contient.\ -Il est possible de trouver ces informations dans le [code source ici](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276) : +L'en-tête magique de la Code Signature est **`0xFADE0CC0`**. Ensuite vous avez des informations telles que la longueur et le nombre de blobs du superBlob qui les contient.\ +Il est possible de trouver ces informations dans le [source code here](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276): ```c /* * Structure of an embedded-signature SuperBlob @@ -38,8 +43,8 @@ char data[]; } CS_GenericBlob __attribute__ ((aligned(1))); ``` -Les blobs courants contenus sont le Code Directory, les Requirements et les Entitlements, ainsi qu'un Cryptographic Message Syntax (CMS).\ -De plus, notez comment les données encodées dans les blobs sont encodées en **Big Endian.** +Les blobs couramment présents sont Code Directory, Requirements et Entitlements ainsi qu'une Cryptographic Message Syntax (CMS).\ +De plus, notez que les données encodées dans les blobs le sont en **Big Endian.** De plus, les signatures peuvent être détachées des binaires et stockées dans `/var/db/DetachedSignatures` (utilisé par iOS). @@ -101,12 +106,12 @@ char end_withLinkage[0]; } CS_CodeDirectory __attribute__ ((aligned(1))); ``` -Notez qu'il existe différentes versions de cette structure où les anciennes peuvent contenir moins d'informations. +Notez qu'il existe différentes versions de cette struct, les anciennes pouvant contenir moins d'informations. -## Pages de signature de code +## Signature des pages de code -Hacher le binaire complet serait inefficace et même inutile s'il n'est chargé en mémoire que partiellement. Par conséquent, la signature de code est en réalité un hachage de hachages où chaque page binaire est hachée individuellement.\ -En fait, dans le code **Code Directory** précédent, vous pouvez voir que la **taille de la page est spécifiée** dans l'un de ses champs. De plus, si la taille du binaire n'est pas un multiple de la taille d'une page, le champ **CodeLimit** spécifie où se termine la signature. +Le hachage du binaire complet serait inefficace et même inutile s'il n'est chargé en mémoire que partiellement. Par conséquent, la signature du code est en réalité un hachage de hachages où chaque page binaire est hachée individuellement.\ +En fait, dans le précédent **Code Directory**, vous pouvez voir que la **taille de page est spécifiée** dans l'un de ses champs. De plus, si la taille du binaire n'est pas un multiple de la taille d'une page, le champ **CodeLimit** précise où se termine la signature. ```bash # Get all hashes of /bin/ps codesign -d -vvvvvv /bin/ps @@ -144,25 +149,25 @@ openssl sha256 /tmp/*.page.* ``` ## Entitlements Blob -Notez que les applications peuvent également contenir un **entitlement blob** où tous les droits sont définis. De plus, certains binaires iOS peuvent avoir leurs droits spécifiques dans l'emplacement spécial -7 (au lieu de l'emplacement spécial -5 des droits). +Notez que les applications peuvent aussi contenir un **entitlement blob** où tous les entitlements sont définis. De plus, certains binaires iOS peuvent avoir leurs entitlements spécifiés dans le slot spécial -7 (au lieu du slot spécial -5 pour les entitlements). -## Special Slots +## Slots spéciaux -Les applications MacOS n'ont pas tout ce dont elles ont besoin pour s'exécuter à l'intérieur du binaire, mais elles utilisent également des **ressources externes** (généralement à l'intérieur du **bundle** des applications). Par conséquent, il y a des emplacements à l'intérieur du binaire qui contiendront les hachages de certaines ressources externes intéressantes pour vérifier qu'elles n'ont pas été modifiées. +Les applications MacOS n'ont pas tout ce dont elles ont besoin pour s'exécuter uniquement à l'intérieur du binaire ; elles utilisent aussi des **external resources** (généralement à l'intérieur du **bundle** de l'application). Par conséquent, il existe des slots dans le binaire qui contiendront les hashes de certaines ressources externes intéressantes pour vérifier qu'elles n'ont pas été modifiées. -En fait, il est possible de voir dans les structures du Code Directory un paramètre appelé **`nSpecialSlots`** indiquant le nombre d'emplacements spéciaux. Il n'y a pas d'emplacement spécial 0 et les plus courants (de -1 à -6) sont : +En pratique, il est possible de voir dans les Code Directory structs un paramètre appelé **`nSpecialSlots`** indiquant le nombre de slots spéciaux. Il n'existe pas de slot spécial 0 et les plus courants (de -1 à -6) sont : -- Hachage de `info.plist` (ou celui à l'intérieur de `__TEXT.__info__plist`). -- Hachage des Exigences -- Hachage du Répertoire de Ressources (hachage du fichier `_CodeSignature/CodeResources` à l'intérieur du bundle). +- Hachage de `info.plist` (ou celui dans `__TEXT.__info__plist`). +- Hachage des Requirements +- Hachage du Resource Directory (hachage du fichier `_CodeSignature/CodeResources` à l'intérieur du bundle). - Spécifique à l'application (non utilisé) -- Hachage des droits -- Signatures de code DMG uniquement -- Droits DER +- Hachage des entitlements +- Uniquement pour les signatures de code DMG +- Entitlements DER -## Code Signing Flags +## Flags de signature de code -Chaque processus a un bitmask associé connu sous le nom de `status` qui est initialisé par le noyau et certains d'entre eux peuvent être remplacés par la **signature de code**. Ces drapeaux qui peuvent être inclus dans la signature de code sont [définis dans le code](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36) : +Chaque processus a associé un bitmask connu sous le nom de `status` qui est initialisé par le kernel et dont certains bits peuvent être remplacés par la **code signature**. Ces flags qui peuvent être inclus dans la code signing sont [définis dans le code](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36): ```c /* code signing attributes of a process */ #define CS_VALID 0x00000001 /* dynamically valid */ @@ -207,15 +212,15 @@ CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_RUNTIME | CS_LINKER_SIGNED) #define CS_ENTITLEMENT_FLAGS (CS_GET_TASK_ALLOW | CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_NVRAM_UNRESTRICTED) ``` -Notez que la fonction [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) peut également ajouter dynamiquement les drapeaux `CS_EXEC_*` lors du démarrage de l'exécution. +Notez que la fonction [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) peut également ajouter dynamiquement les flags `CS_EXEC_*` lors du démarrage de l'exécution. ## Exigences de signature de code -Chaque application stocke des **exigences** qu'elle doit **satisfaire** pour pouvoir être exécutée. Si les **exigences de l'application ne sont pas satisfaites par l'application**, elle ne sera pas exécutée (car elle a probablement été modifiée). +Chaque application contient certaines **exigences** qu'elle doit **satisfaire** pour pouvoir être exécutée. Si les **exigences contenues par l'application ne sont pas satisfaites**, elle ne sera pas exécutée (car elle a probablement été altérée). -Les exigences d'un binaire utilisent une **grammaire spéciale** qui est un flux d'**expressions** et sont encodées sous forme de blobs en utilisant `0xfade0c00` comme magie dont le **hash est stocké dans un emplacement de code spécial**. +Les exigences d'un binaire utilisent une **grammaire spéciale** qui est un flux d'**expressions** et sont encodées en blobs en utilisant `0xfade0c00` comme valeur magique dont le **hachage est stocké dans un emplacement de code spécial**. -Les exigences d'un binaire peuvent être vues en exécutant : +Les exigences d'un binaire peuvent être affichées en exécutant : ```bash codesign -d -r- /bin/ls Executable=/bin/ls @@ -225,10 +230,10 @@ codesign -d -r- /Applications/Signal.app/ Executable=/Applications/Signal.app/Contents/MacOS/Signal designated => identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR ``` -> [!NOTE] -> Notez comment ces signatures peuvent vérifier des éléments tels que les informations de certification, TeamID, IDs, droits et de nombreuses autres données. +> [!TIP] +> Remarquez comment ces signatures peuvent vérifier des éléments tels que les informations de certification, TeamID, IDs, entitlements et bien d'autres données. -De plus, il est possible de générer des exigences compilées en utilisant l'outil `csreq` : +De plus, il est possible de générer certaines exigences compilées en utilisant l'outil `csreq` : ```bash # Generate compiled requirements csreq -b /tmp/output.csreq -r='identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR' @@ -240,57 +245,57 @@ od -A x -t x1 /tmp/output.csreq 0000020 00 00 00 21 6f 72 67 2e 77 68 69 73 70 65 72 73 [...] ``` -Il est possible d'accéder à ces informations et de créer ou modifier des exigences avec certaines API du `Security.framework` comme : +Il est possible d'accéder à ces informations et de créer ou modifier des Requirements via certaines APIs de `Security.framework`, par exemple : -#### **Vérification de Validité** +#### **Checking Validity** -- **`Sec[Static]CodeCheckValidity`** : Vérifie la validité de SecCodeRef par exigence. -- **`SecRequirementEvaluate`** : Valide l'exigence dans le contexte du certificat. -- **`SecTaskValidateForRequirement`** : Valide un SecTask en cours par rapport à l'exigence `CFString`. +- **`Sec[Static]CodeCheckValidity`**: Vérifie la validité d'un SecCodeRef par rapport à un Requirement. +- **`SecRequirementEvaluate`**: Valide un Requirement dans le contexte d'un certificat. +- **`SecTaskValidateForRequirement`**: Valide une SecTask en cours d'exécution contre un Requirement de type `CFString`. -#### **Création et Gestion des Exigences de Code** +#### **Creating and Managing Code Requirements** -- **`SecRequirementCreateWithData` :** Crée un `SecRequirementRef` à partir de données binaires représentant l'exigence. -- **`SecRequirementCreateWithString` :** Crée un `SecRequirementRef` à partir d'une expression de chaîne de l'exigence. -- **`SecRequirementCopy[Data/String]`** : Récupère la représentation des données binaires d'un `SecRequirementRef`. -- **`SecRequirementCreateGroup`** : Crée une exigence pour l'appartenance à un groupe d'applications. +- **`SecRequirementCreateWithData`:** Crée un `SecRequirementRef` à partir de données binaires représentant le Requirement. +- **`SecRequirementCreateWithString`:** Crée un `SecRequirementRef` à partir d'une expression string du Requirement. +- **`SecRequirementCopy[Data/String]`**: Récupère la représentation binaire d'un `SecRequirementRef`. +- **`SecRequirementCreateGroup`**: Crée un Requirement pour l'appartenance à un app-group. -#### **Accès aux Informations de Signature de Code** +#### **Accessing Code Signing Information** -- **`SecStaticCodeCreateWithPath`** : Initialise un objet `SecStaticCodeRef` à partir d'un chemin de système de fichiers pour inspecter les signatures de code. -- **`SecCodeCopySigningInformation`** : Obtient des informations de signature à partir d'un `SecCodeRef` ou `SecStaticCodeRef`. +- **`SecStaticCodeCreateWithPath`**: Initialise un objet `SecStaticCodeRef` à partir d'un chemin de système de fichiers pour inspecter les signatures de code. +- **`SecCodeCopySigningInformation`**: Obtient les informations de signature depuis un `SecCodeRef` ou un `SecStaticCodeRef`. -#### **Modification des Exigences de Code** +#### **Modifying Code Requirements** -- **`SecCodeSignerCreate`** : Crée un objet `SecCodeSignerRef` pour effectuer des opérations de signature de code. -- **`SecCodeSignerSetRequirement`** : Définit une nouvelle exigence que le signataire de code doit appliquer lors de la signature. -- **`SecCodeSignerAddSignature`** : Ajoute une signature au code en cours de signature avec le signataire spécifié. +- **`SecCodeSignerCreate`**: Crée un objet `SecCodeSignerRef` pour effectuer des opérations de code signing. +- **`SecCodeSignerSetRequirement`**: Définit un nouveau Requirement que le signataire appliquera lors du signing. +- **`SecCodeSignerAddSignature`**: Ajoute une signature au code en cours de signature avec le signataire spécifié. -#### **Validation du Code avec des Exigences** +#### **Validating Code with Requirements** -- **`SecStaticCodeCheckValidity`** : Valide un objet de code statique par rapport aux exigences spécifiées. +- **`SecStaticCodeCheckValidity`**: Valide un objet de code statique contre des Requirements spécifiés. -#### **API Utiles Supplémentaires** +#### **Additional Useful APIs** -- **`SecCodeCopy[Internal/Designated]Requirement` : Obtenir SecRequirementRef à partir de SecCodeRef** -- **`SecCodeCopyGuestWithAttributes`** : Crée un `SecCodeRef` représentant un objet de code basé sur des attributs spécifiques, utile pour le sandboxing. -- **`SecCodeCopyPath`** : Récupère le chemin du système de fichiers associé à un `SecCodeRef`. -- **`SecCodeCopySigningIdentifier`** : Obtient l'identifiant de signature (par exemple, Team ID) à partir d'un `SecCodeRef`. -- **`SecCodeGetTypeID`** : Renvoie l'identifiant de type pour les objets `SecCodeRef`. -- **`SecRequirementGetTypeID`** : Obtient un CFTypeID d'un `SecRequirementRef`. +- **`SecCodeCopy[Internal/Designated]Requirement`: Get SecRequirementRef from SecCodeRef** +- **`SecCodeCopyGuestWithAttributes`**: Crée un `SecCodeRef` représentant un objet de code basé sur des attributs spécifiques, utile pour le sandboxing. +- **`SecCodeCopyPath`**: Récupère le chemin du système de fichiers associé à un `SecCodeRef`. +- **`SecCodeCopySigningIdentifier`**: Obtient l'identifiant de signature (par ex. Team ID) depuis un `SecCodeRef`. +- **`SecCodeGetTypeID`**: Renvoie l'identifiant de type pour les objets `SecCodeRef`. +- **`SecRequirementGetTypeID`**: Obtient un CFTypeID d'un `SecRequirementRef`. -#### **Drapeaux et Constantes de Signature de Code** +#### **Code Signing Flags and Constants** -- **`kSecCSDefaultFlags`** : Drapeaux par défaut utilisés dans de nombreuses fonctions du Security.framework pour les opérations de signature de code. -- **`kSecCSSigningInformation`** : Drapeau utilisé pour spécifier que les informations de signature doivent être récupérées. +- **`kSecCSDefaultFlags`**: Flags par défaut utilisés dans de nombreuses fonctions de Security.framework pour les opérations de code signing. +- **`kSecCSSigningInformation`**: Flag utilisé pour spécifier que les informations de signature doivent être récupérées. -## Application de la Signature de Code +## Application de la vérification des signatures de code -Le **noyau** est celui qui **vérifie la signature de code** avant de permettre l'exécution du code de l'application. De plus, une façon de pouvoir écrire et exécuter un nouveau code en mémoire est d'abuser de JIT si `mprotect` est appelé avec le drapeau `MAP_JIT`. Notez que l'application a besoin d'un droit spécial pour pouvoir faire cela. +Le **noyau** est celui qui **vérifie la signature du code** avant d'autoriser l'exécution du code de l'application. De plus, une manière de pouvoir écrire et exécuter en mémoire du nouveau code est d'abuser du JIT si `mprotect` est appelé avec le flag `MAP_JIT`. Notez que l'application a besoin d'un entitlement spécial pour pouvoir le faire. ## `cs_blobs` & `cs_blob` -[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) la structure contient des informations sur le droit du processus en cours. `csb_platform_binary` informe également si l'application est un binaire de plateforme (ce qui est vérifié à différents moments par le système d'exploitation pour appliquer des mécanismes de sécurité comme protéger les droits SEND aux ports de tâche de ces processus). +[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) struct contient les informations sur l'entitlement du processus en cours. `csb_platform_binary` informe également si l'application est un platform binary (ce qui est vérifié à différents moments par l'OS pour appliquer des mécanismes de sécurité, par exemple pour protéger les SEND rights vers les task ports de ces processus). ```c struct cs_blob { struct cs_blob *csb_next;