Learn & practice AWS Hacking:<imgsrc="/.gitbook/assets/arte.png"alt=""data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<imgsrc="/.gitbook/assets/arte.png"alt=""data-size="line">\
Learn & practice GCP Hacking: <imgsrc="/.gitbook/assets/grte.png"alt=""data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<imgsrc="/.gitbook/assets/grte.png"alt=""data-size="line">](https://training.hacktricks.xyz/courses/grte)
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
Os binários do Mac OS geralmente são compilados como **binários universais**. Um **binário universal** pode **suportar múltiplas arquiteturas no mesmo arquivo**.
O cabeçalho tem os bytes **mágicos** seguidos pelo **número** de **arquiteturas** que o arquivo **contém** (`nfat_arch`) e cada arquitetura terá uma struct `fat_arch`.
Como você pode estar pensando, geralmente um binário universal compilado para 2 arquiteturas **dobra o tamanho** de um compilado para apenas 1 arquitetura.
O cabeçalho contém informações básicas sobre o arquivo, como bytes mágicos para identificá-lo como um arquivo Mach-O e informações sobre a arquitetura alvo. Você pode encontrá-lo em: `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"`
Existem diferentes tipos de arquivos, que podem ser encontrados definidos no [**código-fonte, por exemplo aqui**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL\_HEADERS/mach-o/loader.h). Os mais importantes são:
*`MH_OBJECT`: Arquivo objeto relocável (produtos intermediários da compilação, ainda não executáveis).
*`MH_EXECUTE`: Arquivos executáveis.
*`MH_FVMLIB`: Arquivo de biblioteca VM fixa.
*`MH_CORE`: Dumps de código.
*`MH_PRELOAD`: Arquivo executável pré-carregado (não mais suportado no XNU).
*`MH_DYLIB`: Bibliotecas dinâmicas.
*`MH_DYLINKER`: Linker dinâmico.
*`MH_BUNDLE`: "Arquivos de plugin". Gerados usando -bundle no gcc e carregados explicitamente por `NSBundle` ou `dlopen`.
*`MH_DYSM`: Arquivo companheiro `.dSym` (arquivo com símbolos para depuração).
O **layout do arquivo na memória** é especificado aqui, detalhando a **localização da tabela de símbolos**, o contexto da thread principal no início da execução e as **bibliotecas compartilhadas** necessárias. Instruções são fornecidas ao carregador dinâmico **(dyld)** sobre o processo de carregamento do binário na memória.
Existem cerca de **50 tipos diferentes de comandos de carregamento** que o sistema trata de maneira diferente. Os mais comuns são: `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB` e `LC_CODE_SIGNATURE`.
Basicamente, este tipo de Comando de Carregamento define **como carregar o \_\_TEXT** (código executável) **e \_\_DATA** (dados para o processo) **segmentos** de acordo com os **offsets indicados na seção de Dados** quando o binário é executado.
Existem **diferentes tipos** de segmentos, como o **\_\_TEXT** segmento, que contém o código executável de um programa, e o **\_\_DATA** segmento, que contém dados usados pelo processo. Esses **segmentos estão localizados na seção de dados** do arquivo Mach-O.
**Cada segmento** pode ser ainda **dividido** em múltiplas **seções**. A **estrutura do comando de carregamento** contém **informações** sobre **essas seções** dentro do respectivo segmento.
Se você **adicionar** o **offset da seção** (0x37DC) + o **offset** onde a **arquitetura começa**, neste caso `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
* **`__PAGEZERO`:** Instruções para o kernel **mapear** o **endereço zero** para que **não possa ser lido, escrito ou executado**. As variáveis maxprot e minprot na estrutura são definidas como zero para indicar que **não há direitos de leitura-gravação-execução nesta página**.
* Esta alocação é importante para **mitigar vulnerabilidades de desreferência de ponteiro NULL**. Isso ocorre porque o XNU impõe uma página zero rígida que garante que a primeira página (apenas a primeira) da memória seja inacessível (exceto em i386). Um binário poderia atender a esses requisitos criando um pequeno \_\_PAGEZERO (usando o `-pagezero_size`) para cobrir os primeiros 4k e tendo o restante da memória de 32 bits acessível tanto em modo de usuário quanto em modo kernel.
* **`__TEXT`**: Contém **código****executável** com permissões de **leitura** e **execução** (sem permissões de escrita). Seções comuns deste segmento:
*`__text`: Código binário compilado
*`__const`: Dados constantes (somente leitura)
*`__[c/u/os_log]string`: Constantes de string C, Unicode ou logs do os
*`__stubs` e `__stubs_helper`: Envolvidos durante o processo de carregamento da biblioteca dinâmica
*`__unwind_info`: Dados de desempilhamento.
* Note que todo esse conteúdo é assinado, mas também marcado como executável (criando mais opções para exploração de seções que não necessariamente precisam desse privilégio, como seções dedicadas a strings).
* **`__DATA`**: Contém dados que são **legíveis** e **graváveis** (sem executável).
*`__got:` Tabela de Deslocamento Global
*`__nl_symbol_ptr`: Ponteiro de símbolo não preguiçoso (vinculado no carregamento)
*`__la_symbol_ptr`: Ponteiro de símbolo preguiçoso (vinculado no uso)
*`__const`: Deveria ser dados somente leitura (não é realmente)
*`__cfstring`: Strings do CoreFoundation
*`__data`: Variáveis globais (que foram inicializadas)
*`__bss`: Variáveis estáticas (que não foram inicializadas)
*`__objc_*` (\_\_objc\_classlist, \_\_objc\_protolist, etc): Informações usadas pelo runtime do Objective-C
* **`__DATA_CONST`**: \_\_DATA.\_\_const não é garantido que seja constante (permissões de escrita), nem outros ponteiros e a GOT. Esta seção torna `__const`, alguns inicializadores e a tabela GOT (uma vez resolvida) **somente leitura** usando `mprotect`.
* **`__LINKEDIT`**: Contém informações para o linker (dyld), como entradas de tabela de símbolos, strings e relocação. É um contêiner genérico para conteúdos que não estão em `__TEXT` ou `__DATA` e seu conteúdo é descrito em outros comandos de carregamento.
* Informações do dyld: Rebase, opcodes de vinculação não preguiçosa/preguiçosa/fraca e informações de exportação
* Inícios de funções: Tabela de endereços de início de funções
* Dados em Código: Ilhas de dados em \_\_text
* Tabela de Símbolos: Símbolos no binário
* Tabela de Símbolos Indiretos: Símbolos de ponteiro/stub
* Tabela de Strings
* Assinatura de Código
* **`__OBJC`**: Contém informações usadas pelo runtime do Objective-C. Embora essas informações também possam ser encontradas no segmento \_\_DATA, dentro de várias seções em \_\_objc\_\*.
* **`__RESTRICT`**: Um segmento sem conteúdo com uma única seção chamada **`__restrict`** (também vazia) que garante que, ao executar o binário, ele ignorará variáveis ambientais DYLD.
Como foi possível ver no código, **os segmentos também suportam flags** (embora não sejam muito utilizados):
*`SG_HIGHVM`: Apenas núcleo (não utilizado)
*`SG_FVMLIB`: Não utilizado
*`SG_NORELOC`: O segmento não tem relocação
*`SG_PROTECTED_VERSION_1`: Criptografia. Usado, por exemplo, pelo Finder para criptografar o segmento `__TEXT`.
**`LC_MAIN`** contém o ponto de entrada no atributo **entryoff**. No momento do carregamento, **dyld** simplesmente **adiciona** esse valor à (em memória) **base do binário**, então **salta** para essa instrução para iniciar a execução do código do binário.
**`LC_UNIXTHREAD`** contém os valores que o registrador deve ter ao iniciar a thread principal. Isso já foi descontinuado, mas **`dyld`** ainda o utiliza. É possível ver os valores dos registradores definidos por isso com:
Contém informações sobre a **assinatura de código do arquivo Macho-O**. Ele contém apenas um **offset** que **aponta** para o **blob de assinatura**. Isso geralmente está no final do arquivo.\
No entanto, você pode encontrar algumas informações sobre esta seção em [**este post de blog**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) e neste [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4).
Suporte para criptografia binária. No entanto, é claro que, se um atacante conseguir comprometer o processo, ele poderá despejar a memória sem criptografia.
Contém o **caminho para o executável do linker dinâmico** que mapeia bibliotecas compartilhadas no espaço de endereço do processo. O **valor é sempre definido como `/usr/lib/dyld`**. É importante notar que no macOS, o mapeamento de dylib acontece em **modo de usuário**, não em modo de kernel.
Obsoleto, mas quando configurado para gerar dumps em caso de pânico, um core dump Mach-O é criado e a versão do kernel é definida no comando `LC_IDENT`.
UUID aleatório. É útil para qualquer coisa diretamente, mas o XNU o armazena em cache com o resto das informações do processo. Pode ser usado em relatórios de falhas.
Permite indicar variáveis de ambiente para o dyld antes que o processo seja executado. Isso pode ser muito perigoso, pois pode permitir a execução de código arbitrário dentro do processo, então este comando de carga é usado apenas em builds do dyld com `#define SUPPORT_LC_DYLD_ENVIRONMENT` e restringe ainda mais o processamento apenas para variáveis da forma `DYLD_..._PATH` especificando caminhos de carga.
Este comando de carga descreve uma dependência de **biblioteca****dinâmica** que **instrui** o **loader** (dyld) a **carregar e vincular a referida biblioteca**. Há um comando de carga `LC_LOAD_DYLIB`**para cada biblioteca** que o binário Mach-O requer.
No núcleo do arquivo está a região de dados, que é composta por vários segmentos conforme definido na região de comandos de carregamento. **Uma variedade de seções de dados pode ser hospedada dentro de cada segmento**, com cada seção **contendo código ou dados** específicos a um tipo.
Learn & practice AWS Hacking:<imgsrc="/.gitbook/assets/arte.png"alt=""data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<imgsrc="/.gitbook/assets/arte.png"alt=""data-size="line">\
Learn & practice GCP Hacking: <imgsrc="/.gitbook/assets/grte.png"alt=""data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<imgsrc="/.gitbook/assets/grte.png"alt=""data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.