# Binarios universales de macOS & Formato Mach-O
Aprende hacking en AWS de cero a h茅roe con htARTE (HackTricks AWS Red Team Expert)! Otras formas de apoyar a HackTricks: * Si quieres ver a tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCI脫N**](https://github.com/sponsors/carlospolop)! * Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com) * Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colecci贸n de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos * **脷nete al** 馃挰 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **s铆gueme** en **Twitter** 馃惁 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Informaci贸n B谩sica Los binarios de Mac OS suelen compilarse como **binarios universales**. Un **binario universal** puede **soportar m煤ltiples arquitecturas en el mismo archivo**. Estos binarios siguen la **estructura Mach-O**, que b谩sicamente est谩 compuesta por: * Encabezado * Comandos de Carga * Datos ![](<../../../.gitbook/assets/image (559).png>) ## Encabezado Fat Busca el archivo con: `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 o FAT_MAGIC_64 */
	uint32_t	nfat_arch;	/* n煤mero de estructuras que siguen */
};

struct fat_arch {
cpu_type_t	cputype;	/* especificador de cpu (int) */
cpu_subtype_t	cpusubtype;	/* especificador de m谩quina (int) */
uint32_t	offset;		/* desplazamiento en el archivo a este archivo objeto */
uint32_t	size;		/* tama帽o de este archivo objeto */
uint32_t	align;		/* alineaci贸n como potencia de 2 */
};
El encabezado tiene los bytes **magic** seguidos por el **n煤mero** de **archs** que el archivo **contiene** (`nfat_arch`) y cada arch tendr谩 una estructura `fat_arch`. Compru茅balo con:
% 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 (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
fat_magic FAT_MAGIC
nfat_arch 2
architecture x86_64
    cputype CPU_TYPE_X86_64
cpusubtype CPU_SUBTYPE_X86_64_ALL
capabilities 0x0
    offset 16384
    size 72896
    align 2^14 (16384)
architecture arm64e
    cputype CPU_TYPE_ARM64
cpusubtype CPU_SUBTYPE_ARM64E
capabilities PTR_AUTH_VERSION USERSPACE 0
    offset 98304
    size 88816
    align 2^14 (16384)
o utilizando la herramienta [Mach-O View](https://sourceforge.net/projects/machoview/):
Como podr铆as estar pensando, usualmente un binario universal compilado para 2 arquitecturas **duplica el tama帽o** de uno compilado solo para 1 arquitectura. ## **Encabezado Mach-O** El encabezado contiene informaci贸n b谩sica sobre el archivo, como los bytes m谩gicos para identificarlo como un archivo Mach-O e informaci贸n sobre la arquitectura objetivo. Puedes encontrarlo en: `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) */ struct mach_header { uint32_t magic; /* mach magic number identifier */ cpu_type_t cputype; /* cpu specifier (e.g. I386) */ cpu_subtype_t cpusubtype; /* machine specifier */ uint32_t filetype; /* type of file (usage and alignment for the file) */ uint32_t ncmds; /* number of load commands */ uint32_t sizeofcmds; /* the size of all the load commands */ uint32_t flags; /* flags */ }; #define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ struct mach_header_64 { uint32_t magic; /* mach magic number identifier */ int32_t cputype; /* cpu specifier */ int32_t cpusubtype; /* machine specifier */ uint32_t filetype; /* type of file */ uint32_t ncmds; /* number of load commands */ uint32_t sizeofcmds; /* the size of all the load commands */ uint32_t flags; /* flags */ uint32_t reserved; /* reserved */ }; ``` **Tipos de archivos**: * MH\_EXECUTE (0x2): Ejecutable Mach-O est谩ndar * MH\_DYLIB (0x6): Biblioteca vinculada din谩micamente Mach-O (p. ej. .dylib) * MH\_BUNDLE (0x8): Un paquete Mach-O (p. ej. .bundle) ```bash # Checking the mac header of a binary otool -arch arm64e -hv /bin/ls Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DYLDLINK TWOLEVEL PIE ``` O utilizando [Mach-O View](https://sourceforge.net/projects/machoview/):
## **Comandos de carga Mach-O** Esto especifica el **dise帽o del archivo en memoria**. Contiene la **ubicaci贸n de la tabla de s铆mbolos**, el contexto del hilo principal al inicio de la ejecuci贸n y qu茅 **bibliotecas compartidas** se requieren.\ Los comandos b谩sicamente instruyen al cargador din谩mico **(dyld) c贸mo cargar el binario en memoria.** Todos los comandos de carga comienzan con una estructura **load\_command**, definida en el anteriormente mencionado **`loader.h`**: ```objectivec struct load_command { uint32_t cmd; /* type of load command */ uint32_t cmdsize; /* total size of command in bytes */ }; ``` Hay alrededor de **50 tipos diferentes de comandos de carga** que el sistema maneja de manera diferente. Los m谩s comunes son: `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB` y `LC_CODE_SIGNATURE`. ### **LC\_SEGMENT/LC\_SEGMENT\_64** {% hint style="success" %} B谩sicamente, este tipo de Comando de Carga define **c贸mo cargar los segmentos \_\_TEXT** (c贸digo ejecutable) **y \_\_DATA** (datos para el proceso) seg煤n los **desplazamientos indicados en la secci贸n de Datos** cuando se ejecuta el binario. {% endhint %} Estos comandos **definen segmentos** que se **mapean** en el **espacio de memoria virtual** de un proceso cuando se ejecuta. Hay **diferentes tipos** de segmentos, como el segmento **\_\_TEXT**, que contiene el c贸digo ejecutable de un programa, y el segmento **\_\_DATA**, que contiene datos utilizados por el proceso. Estos **segmentos se encuentran en la secci贸n de datos** del archivo Mach-O. **Cada segmento** puede dividirse a煤n m谩s en m煤ltiples **secciones**. La **estructura del comando de carga** contiene **informaci贸n** sobre **estas secciones** dentro del segmento respectivo. En el encabezado primero encuentras el **encabezado del segmento**:
struct segment_command_64 { /* para arquitecturas de 64 bits */
uint32_t	cmd;		/* LC_SEGMENT_64 */
uint32_t	cmdsize;	/* incluye sizeof section_64 structs */
char		segname[16];	/* nombre del segmento */
uint64_t	vmaddr;		/* direcci贸n de memoria de este segmento */
uint64_t	vmsize;		/* tama帽o de memoria de este segmento */
uint64_t	fileoff;	/* desplazamiento del archivo de este segmento */
uint64_t	filesize;	/* cantidad a mapear desde el archivo */
int32_t		maxprot;	/* m谩xima protecci贸n de VM */
int32_t		initprot;	/* protecci贸n inicial de VM */
	uint32_t	nsects;		/* n煤mero de secciones en el segmento */
	uint32_t	flags;		/* banderas */
};
Ejemplo de encabezado de segmento:
Este encabezado define el **n煤mero de secciones cuyos encabezados aparecen despu茅s** de 茅l: ```c struct section_64 { /* for 64-bit architectures */ char sectname[16]; /* name of this section */ char segname[16]; /* segment this section goes in */ uint64_t addr; /* memory address of this section */ uint64_t size; /* size in bytes of this section */ uint32_t offset; /* file offset of this section */ uint32_t align; /* section alignment (power of 2) */ uint32_t reloff; /* file offset of relocation entries */ uint32_t nreloc; /* number of relocation entries */ uint32_t flags; /* flags (section type and attributes)*/ uint32_t reserved1; /* reserved (for offset or index) */ uint32_t reserved2; /* reserved (for count or sizeof) */ uint32_t reserved3; /* reserved */ }; ``` Ejemplo de **encabezado de secci贸n**:
Si **a帽ades** el **desplazamiento de la secci贸n** (0x37DC) + el **desplazamiento** donde **comienza la arquitectura**, en este caso `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
Tambi茅n es posible obtener **informaci贸n de los encabezados** desde la **l铆nea de comandos** con: ```bash otool -lv /bin/ls ``` Segmentos comunes cargados por este cmd: * **`__PAGEZERO`:** Instruye al kernel para **mapear** la **direcci贸n cero** de modo que **no se pueda leer, escribir o ejecutar**. Las variables maxprot y minprot en la estructura se establecen en cero para indicar que **no hay derechos de lectura-escritura-ejecuci贸n en esta p谩gina**. * Esta asignaci贸n es importante para **mitigar vulnerabilidades de desreferenciaci贸n de punteros NULL**. * **`__TEXT`**: Contiene **c贸digo ejecutable** con permisos de **lectura** y **ejecuci贸n** (no escribible). Secciones comunes de este segmento: * `__text`: C贸digo binario compilado * `__const`: Datos constantes * `__cstring`: Constantes de cadena * `__stubs` y `__stubs_helper`: Involucrados durante el proceso de carga de bibliotecas din谩micas * **`__DATA`**: Contiene datos que son **legibles** y **escribibles** (no ejecutables). * `__data`: Variables globales (que han sido inicializadas) * `__bss`: Variables est谩ticas (que no han sido inicializadas) * `__objc_*` (\_\_objc\_classlist, \_\_objc\_protolist, etc): Informaci贸n utilizada por el tiempo de ejecuci贸n de Objective-C * **`__LINKEDIT`**: Contiene informaci贸n para el enlazador (dyld) como, "entradas de tabla de s铆mbolos, cadenas y reubicaci贸n." * **`__OBJC`**: Contiene informaci贸n utilizada por el tiempo de ejecuci贸n de Objective-C. Aunque esta informaci贸n tambi茅n puede encontrarse en el segmento \_\_DATA, dentro de varias secciones en \_\_objc\_\*. ### **`LC_MAIN`** Contiene el punto de entrada en el **atributo entryoff.** En el momento de la carga, **dyld** simplemente **suma** este valor a la **base (en memoria) del binario**, y luego **salta** a esta instrucci贸n para comenzar la ejecuci贸n del c贸digo del binario. ### **LC\_CODE\_SIGNATURE** Contiene informaci贸n sobre la **firma de c贸digo del archivo Mach-O**. Solo contiene un **desplazamiento** que **apunta** al **blob de firma**. Esto est谩 t铆picamente al final del archivo.\ Sin embargo, puedes encontrar informaci贸n sobre esta secci贸n en [**este post del blog**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) y en estos [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4). ### **LC\_LOAD\_DYLINKER** Contiene la **ruta al ejecutable del enlazador din谩mico** que mapea las bibliotecas compartidas en el espacio de direcciones del proceso. El **valor siempre se establece en `/usr/lib/dyld`**. Es importante notar que en macOS, el mapeo de dylib ocurre en **modo usuario**, no en modo kernel. ### **`LC_LOAD_DYLIB`** Este comando de carga describe una dependencia de **biblioteca din谩mica** que **instruye** al **cargador** (dyld) para **cargar y enlazar dicha biblioteca**. Hay un comando de carga LC\_LOAD\_DYLIB **para cada biblioteca** que el binario Mach-O requiere. * Este comando de carga es una estructura de tipo **`dylib_command`** (que contiene una struct dylib, describiendo la biblioteca din谩mica dependiente real): ```objectivec struct dylib_command { uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */ uint32_t cmdsize; /* includes pathname string */ struct dylib dylib; /* the library identification */ }; struct dylib { union lc_str name; /* library's path name */ uint32_t timestamp; /* library's build time stamp */ uint32_t current_version; /* library's current version number */ uint32_t compatibility_version; /* library's compatibility vers number*/ }; ``` Tambi茅n puedes obtener esta informaci贸n desde la CLI con: ```bash otool -L /bin/ls /bin/ls: /usr/lib/libutil.dylib (compatibility version 1.0.0, current version 1.0.0) /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) ``` Algunas bibliotecas potencialmente relacionadas con malware son: * **DiskArbitration**: Monitoreo de unidades USB * **AVFoundation:** Captura de audio y video * **CoreWLAN**: Escaneos de Wifi. {% hint style="info" %} Un binario Mach-O puede contener uno o **m谩s** **constructores**, que se **ejecutar谩n** **antes** de la direcci贸n especificada en **LC\_MAIN**.\ Los desplazamientos de cualquier constructor se encuentran en la secci贸n **\_\_mod\_init\_func** del segmento **\_\_DATA\_CONST**. {% endhint %} ## **Datos de Mach-O** El coraz贸n del archivo es la regi贸n final, los datos, que consiste en una serie de segmentos dispuestos en la regi贸n de comandos de carga. **Cada segmento puede contener varias secciones de datos**. Cada una de estas secciones **contiene c贸digo o datos** de un tipo particular. {% hint style="success" %} Los datos son b谩sicamente la parte que contiene toda la **informaci贸n** que es cargada por los comandos de carga **LC\_SEGMENTS\_64** {% endhint %} ![](<../../../.gitbook/assets/image (507) (3).png>) Esto incluye: * **Tabla de funciones:** Que contiene informaci贸n sobre las funciones del programa. * **Tabla de s铆mbolos**: Que contiene informaci贸n sobre la funci贸n externa utilizada por el binario * Tambi茅n podr铆a contener nombres de funciones internas, variables y m谩s. Para verificarlo, podr铆as usar la herramienta [**Mach-O View**](https://sourceforge.net/projects/machoview/):
O desde la cli: ```bash size -m /bin/ls ```
Aprende hacking en AWS de cero a h茅roe con htARTE (HackTricks AWS Red Team Expert)! Otras formas de apoyar a HackTricks: * Si quieres ver a tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCI脫N**](https://github.com/sponsors/carlospolop)! * Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com) * Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colecci贸n de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos * **脷nete al** 馃挰 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sigue** a **Twitter** 馃惁 [**@carlospolopm**](https://twitter.com/carlospolopm)**.** * **Comparte tus trucos de hacking enviando PRs a los repositorios de github** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).